Suppose I have two objects of same class for example:
public class Example {
String name;
String rollNo;
String address;
String phoneNo;
String city;
}
Example obj1 = new Example();
obj1.name = "Name";
obj1.rollNo = "10";
obj1.address = "Address";
obj1.phoneNo = "Phone Number";
obj1.city = "City";
Example obj2 = new Example();
obj2.name = "Name";
obj2.rollNo = "10";
obj2.address = "Address";
obj2.phoneNo = "Phone Number";
obj2.city = "City";
Here I want to compare obj1 with obj2 the catch is I don't want to do this with if condition i.e. getting each member variable of obj1 then comparing it with obj2 variable.
equals method of java.lang.Object class will not work here as it compares object reference.
My question is, is there any Java API which will compare two objects and its member variables.
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Example other = (Example) obj;
if (address == null) {
if (other.address != null)
return false;
} else if (!address.equals(other.address))
return false;
if (city == null) {
if (other.city != null)
return false;
} else if (!city.equals(other.city))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (phoneNo == null) {
if (other.phoneNo != null)
return false;
} else if (!phoneNo.equals(other.phoneNo))
return false;
if (rollNo == null) {
if (other.rollNo != null)
return false;
} else if (!rollNo.equals(other.rollNo))
return false;
return true;
}
Paste this equals function into your exmaple class and then compare the objects like this:
if(obj1.equals(obj2)) { //will return true now
}
In Java, there is three alternatives to compare objects :
By overriding the Object.equals() method.
Using the Generic java.util.Comparator Interface
Using the java.lang.Comparable interface
Check this question, and this link for more details.
Related
I have a person class with overridden hashcode and equals, looks something like this :
class PersonKey {
private String personUID;
private String ssnUID;
private String countryCode;
public PersonKey (
String personUID, String ssnUID, String countryCode) {
this.personUID= personUID;
this.ssnUID= countryCode;
this.countryCode= countryCode;
}
.....
}
This class already had personUID and ssnUID fields and I am introducing countryCode as a new field.
This class already had a complicated hashcode and equals method, with the inclusion of countryCode the logic got even more complicated. Is there a way I can reduce the Cyclomatic Complexity using inheritance or wrapper class?
HashCode :
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result;
if (personUID != null) result += personUID.hashCode();
else result += ((ssnUID == null) ? 0 : ssnUID.hashCode());
if ((personUID != null || ssnUID != null)
&& (countryCode != null)) {
result += countryCode.hashCode();
}
return result;
}
Equals :
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
PersonKey other = (PersonKey) obj;
if (!getOuterType().equals(other.getOuterType())) {
return false;
}
// For the purposes of mapping any "empty" Person (null
// personUID and ssnUID) is considered to be unique so return
// false
if ((ssnUID == null) && (personUID == null)) {
return false;
}
// Only evaluate ssnUID if the personUID is null
if (personUID == null) {
// If the current ssnUID matches the personUID
// from the other key the keys will be assumed to match
if (ssnUID.equals(other.personUID)) {
if (StringUtils.isBlank(countryCode) && StringUtils.isBlank(other.countryCode)) {
return true;
} else {
if (countryCode.equals(other.contryCode)) return true;
}
} else if (other.personUID != null) {
return false;
}
if (ssnUID.equals(other.ssnUID)) {
if (StringUtils.isBlank(v) && StringUtils.isBlank(other.countryCode)) {
return true;
} else {
if (countryCode.equals(other.countryCode)) return true;
}
}
}
// If the current personUID matches the personUID
// the keys will
// be considered a match regardless of the value of the ssnUID.
else if (personUID .equals(other.personUID)) {
if (StringUtils.isBlank(contryCode) && StringUtils.isBlank(other.contryCode)) {
return true;
} else {
if (countryCode.equals(other.countryCode)) return true;
}
}
// If the current personUID matches the ssnUID
// from the other key, and the other keys personUID is null
// the keys will be considered a match
else if ((other.personUID == null)
&& (personUID.equals(other.ssnUID))) {
if (StringUtils.isBlank(contryCode) && StringUtils.isBlank(other.contryCode)) {
return true;
} else {
if (countryCode.equals(other.countryCode)) return true;
}
}
return false;
}
You can use Lombok's #EqualsAndHashCode would be the fastest option.
Example and documentation can be found here: https://projectlombok.org/features/EqualsAndHashCode
If you create a new method in your class:
#EqualsAndHashCode(onlyExplicitlyIncluded = true)
class PersonKey {
private String personUID;
private String ssnUID;
private String countryCode;
...
#EqualsAndHashCode.Include
public String uidOrSsn() {
return personUID != null ? personUID : ssnUID;
}
}
This way you're telling Lombok to only create the equals and hashCode for the uidOrSsn() method declared. Whichever the non-null value of personUID or ssnUID, then it will be generated.
I've a class A which is as follows:
A{
String name;
ArrayList<Bike> firstArray;
ArrayList<Cycle> secondArray;
// it's constructors and related methods are down lines.
}
and I have two instances of it named a_Obj and b_obj. I compare only the variable ,name inside object a_Obj with b_Obj using indexOf.
My question is how to call indexOf in this case and in other words how to tell the compiler that I just want to compare name of two objects regardless of ArrayLists declared inside the class A.
you can override equals() in your class
Given below is how indexOf has been implemented by default:
public int indexOf(Object o) {
ListIterator<E> it = listIterator();
if (o==null) {
while (it.hasNext())
if (it.next()==null)
return it.previousIndex();
} else {
while (it.hasNext())
if (o.equals(it.next()))
return it.previousIndex();
}
return -1;
}
By overriding the equals method in A to consider just the equality of name, you can make it happen.
Given below is the definition generated by Eclipse IDE:
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
A other = (A) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
A shorter version for the same can be as follows:
#Override
public boolean equals(Object obj) {
if (obj == null)
return false;
A other = (A) obj;
return Objects.equals(name, other.name);
}
I have an exam and this was in the mock and im not quite sure how to go about it, this isn't homework its simply trying to understand how to do it. Thanks.
public class Book{
private final String title;
private final String author;
private final int edition;
private Book(String title, String author, int edition)
{
this.title = title;
this.author = author;
this.edition = edition;
}
public String getTitle()
{
return title;
}
public String getAuthor()
{
return author;
}
public String getEdition()
{
return edition;
}
}
I need to provide implementations of equals, hashCode and compareTo methods for the above code.
I'm not to sure how to go about it, would it be somthing similar to this for the compareTo method?
title.compareTo(title);
author.compareTo(author);
edition.compareTo(edition);
Thanks, any help would be greatly appreciated.
your compareTo should be this:
title.compareToIgnoreCase(otherTitle);
...
equals:
if(null == title || null == author || null == editor)
{
return false;
}
if(!title.equals(otherTitle)
{
return false;
}
if(!author.equals(otherAuthor)
{
return false;
}
if(!editor.equals(otherEditor)
{
return false;
}
return true;
Take look at this.
http://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/builder/package-summary.html
You can use the builders in this package to create default implementations.
IDEs like Eclipse can generate hashCode and equals methods for you (Source -> generate hashCode() and equals()). You can even specify which fields of the object need to match for it to be considered "equal".
For instance here is what Eclipse generates for your class:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((author == null) ? 0 : author.hashCode());
result = prime * result + edition;
result = prime * result + ((title == null) ? 0 : title.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Book other = (Book) obj;
if (author == null) {
if (other.author != null)
return false;
} else if (!author.equals(other.author))
return false;
if (edition != other.edition)
return false;
if (title == null) {
if (other.title != null)
return false;
} else if (!title.equals(other.title))
return false;
return true;
}
I was make some code and found that objects ar eno equals - it is trivial question but not understand how default equals works.
class A {
String id;
public A(String id) {
this.id = id;
}
public static void main(String args[])
{
A a = new A("1");
A b = new A("1");
System.out.println(a.id);
System.out.println(b.id);
System.out.println(a.equals(b));
}
}
Result is:
1
1
false
But I want to have a.equals(b) == true why it is false?
Your class currently extends only Object class and in Object class equals method looks like this
public boolean equals(Object obj) {
return (this == obj);
}
What you need is to override this method, for example like this
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
A other = (A) obj;
if (id == other.id)
return true;
if (id == null)
return false;
if (other.id == null)
return false;
if (!this.id.equals(other.id))
return false;
return true;
}
Also when you override equals you probably should override hashCode method, but this is not subject of your question. You can read more about it here.
If you don't override equals() on the object, you are comparing two different memory references. So override equals() to compare the id fields.
It overrides Object's equals method by default, it checks the "same object" rather than "same content". If you want to have a.equals(b) == true, you should override it:
#Override
public boolean equals (Object obj) {
if (obj instanceof A) {
A a = (A) obj;
if (id == null) {
return a.id == null;
} else {
return id.equals(a.id);
}
}
return false;
}
----- EDITED -----
you should rewrite an equals() method for your code, as you would a toString() method.
Basically how do you check if an object is null or empty. What I mean is that if I have an object instantiated but all its values or fields are null, the how do I check in code if it is empty?
I have tried;
if (doc != null){
.... do something
But it doesn't seem to work.
You can't do it directly, you should provide your own way to check this. Eg.
class MyClass {
Object attr1, attr2, attr3;
public boolean isValid() {
return attr1 != null && attr2 != null && attr3 != null;
}
}
Or make all fields final and initialize them in constructors so that you can be sure that everything is initialized.
import org.apache.commons.lang3.ObjectUtils;
if(ObjectUtils.isEmpty(yourObject)){
//your block here
}
This can be done with java reflection,This method returns false if any one attribute value is present for the object ,hope it helps some one
public boolean isEmpty() {
for (Field field : this.getClass().getDeclaredFields()) {
try {
field.setAccessible(true);
if (field.get(this)!=null) {
return false;
}
} catch (Exception e) {
System.out.println("Exception occured in processing");
}
}
return true;
}
You should check it against null.
If you want to check if object x is null or not, you can do:
if(x != null)
But if it is not null, it can have properties which are null or empty. You will check those explicitly:
if(x.getProperty() != null)
For "empty" check, it depends on what type is involved. For a Java String, you usually do:
if(str != null && !str.isEmpty())
As you haven't mentioned about any specific problem with this, difficult to tell.
I suggest you add separate overloaded method and add them to your projects Utility/Utilities class.
To check for Collection be empty or null
public static boolean isEmpty(Collection obj) {
return obj == null || obj.isEmpty();
}
or use Apache Commons CollectionUtils.isEmpty()
To check if Map is empty or null
public static boolean isEmpty(Map<?, ?> value) {
return value == null || value.isEmpty();
}
or use Apache Commons MapUtils.isEmpty()
To check for String empty or null
public static boolean isEmpty(String string) {
return string == null || string.trim().isEmpty();
}
or use Apache Commons StringUtils.isBlank()
To check an object is null is easy but to verify if it's empty is tricky as object can have many private or inherited variables and nested objects which should all be empty. For that All need to be verified or some isEmpty() method be in all objects which would verify the objects emptiness.
If your Object contains Objects then check if they are null, if it have primitives check for their default values.
for Instance:
Person Object
name Property with getter and setter
to check if name is not initialized.
Person p = new Person();
if(p.getName()!=null)
I have a way, you guys tell me how good it is.
Create a new object of the class and compare it with your object (which you want to check for emptiness).
To be correctly able to do it :
Override the hashCode() and equals() methods of your model class and also of the classes, objects of whose are members of your class, for example :
Person class (primary model class) :
public class Person {
private int age;
private String firstName;
private String lastName;
private Address address;
//getters and setters
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((address == null) ? 0 : address.hashCode());
result = prime * result + age;
result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (address == null) {
if (other.address != null)
return false;
} else if (!address.equals(other.address))
return false;
if (age != other.age)
return false;
if (firstName == null) {
if (other.firstName != null)
return false;
} else if (!firstName.equals(other.firstName))
return false;
if (lastName == null) {
if (other.lastName != null)
return false;
} else if (!lastName.equals(other.lastName))
return false;
return true;
}
#Override
public String toString() {
return "Person [age=" + age + ", firstName=" + firstName + ", lastName=" + lastName + ", address=" + address
+ "]";
}
}
Address class (used inside Person class) :
public class Address {
private String line1;
private String line2;
//getters and setters
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((line1 == null) ? 0 : line1.hashCode());
result = prime * result + ((line2 == null) ? 0 : line2.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Address other = (Address) obj;
if (line1 == null) {
if (other.line1 != null)
return false;
} else if (!line1.equals(other.line1))
return false;
if (line2 == null) {
if (other.line2 != null)
return false;
} else if (!line2.equals(other.line2))
return false;
return true;
}
#Override
public String toString() {
return "Address [line1=" + line1 + ", line2=" + line2 + "]";
}
}
Now in the main class :
Person person1 = new Person();
person1.setAge(20);
Person person2 = new Person();
Person person3 = new Person();
if(person1.equals(person2)) --> this will be false
if(person2.equals(person3)) --> this will be true
I hope this is the best way instead of putting if conditions on each and every member variables.
Let me know !
for simple (It's worked in my project).
if null check not mandatory for some fields then exclude it from toString() method as in my above code, I have removed school.
public class Student {
private String name;
private String school;
private Integer roll;
private String section;
//getters and setters
#Override
public String toString() {
return "Student [name=" + name + ", roll=" + roll + ", section=" + section + "]";
}
}
public class StudentRunner {
public static void main(String[] args) {
Student s = new Student();
s.setName("ved");
s.setRoll(12);
s.setSection("A");
s.setSchool(null);//school set null and it removed from toString() method
if(s.toString().contains("null")) {
System.out.println("null value contains");
//do your work here or throw exception
} else {
System.out.println("no null value");
}
}
}
output : no null value
let suppose ,
data = {};
if( if(!$.isEmptyObject(data)))
{
document.write("Object is empty);
}
else{
document.write("Object is not empty);
}
It worked for me and its an easy way to check if object is empty or not