functioning of (== ) in terms of hashCode - java

String s1="abc";
String s2=new String("abc");
when we compare the both
s1==s2; it return false
and when we compare it
with s1.hashCode()==s2.hashCode it return true
i know (==) checks reference id's .Does it returning true in above comparison because above hashCode are saved to same bucket??Please give me explanation

Don't forget that your hash codes are primitive integers, and comparing primitives using == will compare their values, not their references (since primitives don't have references)
Hence two strings having the same contents will yield the same hash code, and a comparison via == is perfectly valid.
The concept of a bucket is only valid when you put an object into a hashed collection (e.g. a HashSet). The value of the hash code dictates which bucket the object goes into. The hash codes themselves aren't stored.

First comparison fails because they are two different objects. Second comparison works because they are comparing the output of the hashCode() function, which produces the same value for both.

When comparing objects using the equality operator (==) you are testing the equality of the Object Reference. Object References are only equal if they are the same object.
What is usually meant is the equality of the concept/information the object encapsulates. And this is best determined by the equal(Object obj) method.
For String this would be:
s1.equals(s2);

When you compare the two Strings using s1==s2, you are comparing references. Since just before that line you created a new String object by copying the old one, both references refer to different objects, even though they contain the same value.
On the other hand, what the hashCode method does, depends on how it is implemented. The specification says that it has to comply with the equals function (whose behavior also depends on how it is implemented in the concrete type): If two objects are equal according to the equals method, they must return the same hash code. Since equals for String compares the values (not the references), both hashCode calls have to return the same value. And since hashCode returns an int, which is a primitive data type, your == comparison actually compares values and therefore works as expected.
Note: If you had done the same experiment for a class different from String that doesn't override the equals and hashCode methods (which is perfectly valid; it's just another way of defining equality on your type of object), it would have returned false for the hashCode comparison, too:
public class MyObject {
private int value;
public MyObject(MyObject toCopy) {
this.value = toCopy.value;
}
public MyObject(int value) {
this.value = value;
}
public static void main(String[] args) {
MyObject s1 = new MyObject(0);
MyObject s2 = new MyObject(s1);
System.out.println(s1 == s2); // false
System.out.println(s1.hashCode() == s2.hashCode()); // false
}
}
It all depends on how the programmer of the class defines which objects to consider equal.

Related

same string but it return false while using equals method with two StringBuilder objects [duplicate]

class strb
{
static public void main(String...string)
{
StringBuilder s1 = new StringBuilder("Test");
StringBuilder s2 = new StringBuilder("Test");
System.out.println(s1); // output: Test
System.out.println(s2); // Test
System.out.println(s1==s2); // false
System.out.println(s1.equals(s2)); //Line 1 output: false
System.out.println(s1.toString()==s2.toString()); //Line 2 output: false
}
}
Just have a quick question on .equals.
Regardless of the object content, does .equals return true only if both the object references point to the same object ?
EDIT : Now I understand the part about the .equals but why does Line 2 not return true ?
EDIT : I believe == looks at the reference variable's address and so s1 and s2 cannot be equal.correct me if my assumption is not right
Yes, StringBuilder does not override Object's .equals() function, which means the two object references are not the same and the result is false.
For StringBuilder, you could use s1.toString().equals(s2.toString())
For your edit, you're calling the == operator on two different String objects. The == operator will return false because the objects are different. To compare Strings, you need to use String.equals() or String.equalsIgnoreCase()
It's the same problem you were having earlier
The StringBuilder class does not provide an overriden equals() method. As such, when that method is called on an instance of StringBuilder, the Object class implementation of the method is executed, since StringBuilder extends Object.
The source code for that is
public boolean equals(Object obj) {
return (this == obj);
}
Which simply compares reference equality.
The default implementation of .equals for the Object class is as you mentioned.
Other classes can override this behavior. StringBuilder is not one of them.
String is one of them, which overrides it to ensure that the String representations of both objects result in the same sequence of characters. String API
Refer to the documentation for the specific object in question.
Check the contract of equals method:
it must be consistent (if the objects are not modified, then it must keep returning the same value).
That's why StringBuilder does not override it regardless of its content.
Let's take example above.
StringBuilder s1 = new StringBuilder("Test");
StringBuilder s2 = new StringBuilder("Test");
Maybe, to you it is expected that s1.equals(s2) returns true due to current run time values.
But what about if you change add line:
s1.append("abc");
Then s1 and s2 will have different string contents and s1.equals(s2) is expected to be false. But it is in contradiction with consistency.
for your first answer check #abmitchell 's Answer
And for your Edit:
In Java, String is an object and we can't compare objects for value equality by using ==
== is used for comparing primitives values or object references.
To compare Object values we use equals() in Java
StringBuilder class doesn't have the implementation of equals() method like one in the String class.
So it executes default Object class functionality, which again checks only for address equivalency, which is not same in this case. so it prints false.
Note 1: You can use == operator on objects also, but it simply checks if the address of both the objects are same or not.
Note 2: == operator plays good role in comparing two String objects created in string constant pool, to find out if it is really creating a new object in string constant pool or not.
StringBuilder and StringBuffer not override the equals function of Object class.but string override the equals method.
the function of Object is this
public boolean equals(Object obj) {
return (this == obj);
}
you could write your code like this.
System.out.println(s1.toString() == s2.toString());
System.out.println(s1.toString().equals(s2.toString()));
Agreed with both of the above responses, but I'm worth noting to actually compare contents you can do:
System.out.println(s1.toString().equals(s2.toString())); //Line 1
Since StringBuilder does not have a equals method, it is best to first change the StringBuilder to String and then check equality.
Eg - sb1.toString().equals(sb2.toString()).
Note: The == operator or sb1 == sb2 will never work here because the two StringBuilder(s) are completely different objects.
As others have said, StringBuilder does not override equals. However, it does implement Comparable (since Java 11). Therefore, you can check s1.compareTo(s2) == 0 to find out if the string representations are equal.

How == and equal works in java in Case of Integer Object? [duplicate]

This question already has answers here:
Java: Integer equals vs. ==
(7 answers)
Closed 4 years ago.
I have found many possible duplicates question on this but none clarifies my doubt on how it works?
Integer a =25654; // a.hashCode()=>25654
Integer b =25654; // b.hashCode()=>25654
System.out.println(a.equals(b)); => true
System.out.println(a == b); => false
I have read this answer somewhere..
If no parent classes have provided an override, then it defaults to the method from the ultimate parent class, Object, and so you're left with the Object#equals(Object o) method. Per the Object API this is the same as ==; that is, it returns true if and only if both variables refer to the same object, if their references are one and the same. Thus you will be testing for object equality and not functional equality.
in this case both object have same memory address(as per hashcode) still why does it returns false when we compare using == ? or the actual memory address is different? please correct me if i am wrong. Thanks
Object.hashCode:
The hashCode method defined by class Object does return distinct
integers for distinct objects.
But Integer.hashCode overrides Object.hashCode:
returns a hash code value for this object, equal to the primitive int
value represented by this Integer object.
which means Integers with same hashCode does not have to share the same object.
The source code of Integer.hashCode
#Override
public int hashCode() {
return Integer.hashCode(value);
}
public static int hashCode(int value) {
return value;
}
If you let:
Integer a = 127;
Integer b = 127;
System.out.println(a.equals(b)); // true
System.out.println(a == b); // true
this is because Integers between [-128, 127] could be cached.
in this case both object have same memory address(as per hashcode)
still why does it returns false when we compare using == ? or the
actual memory address is different? please correct me if i am wrong.
Thanks
The hashcode has not to be considered as the memory address because the internal address of an object may change through the time.
The specification of hashCode() never state that two objects with the same hashcode value refer necessarily the same object.
Even two objects with the same hashcode may not be equals in terms of Object.equals().
But the specification states :
If two objects are equal according to the equals(Object) method, then
calling the hashCode method on each of the two objects must produce
the same integer result.
And this is verifiable in your example :
Integer a =25654; // a.hashCode()=>25654
Integer b =25654; // a.hashCode()=>25654
System.out.println(a.equals(b)); => true
a and b refer to objects that are equals(), and yes their hash code is indeed the same.
Your quotation doesn't refer to hashCode() but to the default Object.equals() method that will be used if no overriding was done for equals().
For example if I don't override equals() and hashCode() for a Foo class :
Foo fooOne = new Foo(1);
Foo fooOneBis = new Foo(1);
fooOne.equals(fooOneBis); // return false
The two objects have the same state but they are not equals as under the hood is used Object.equals() that compares the object itself and not their state.
And indeed equal() will return true only if the variables refer the same object :
Foo foo = new Foo(1);
foo.equals(foo); // return true

what is hash code and how it same for two string and with new string it will give diffrent output?

I am using the same string as str1 and str2 when I compare this it will give true output with same hashcode. but when I use new String it will give different output with same hash code. As per my information == keyword compare string according to hash code but still I get different output?
public class StringClass {
public static void main(String args[]){
String str1="john";
String str2="john";
String str3=new String("john");
String str4=new String("john");
if(str1==str2){
System.out.println("Both string have same hash code");
System.out.println(str1.hashCode());
System.out.println(str2.hashCode());
}
if(str3==str4){
System.out.println("both have same hash code");
System.out.println(str3.hashCode());
System.out.println(str4.hashCode());
}
}
}
No. == compares the references. this means == compares where in the memory the object is saved. hashCode() creates an integer from the attributes of an Object (the algorithm for this operation may vary from class to class). Comparison of objects should be done via o1.equals(o2).
== does NOT use an object's hash to compare. Hash is just a tool for indexing and managing Objects. Two arbitrary objects may produce the same hash code.
Object.equals(Object) gives you the 'equality' as you may understand it, as "my string" is equals to "my string", without taking into account if it's actually the same object or not (both strings may be the same object, or two objects with the same data).
== compares the references, so it returns true only if the two variables contain the pointer to the same data.
You cannot use == when checking for String equality in Java. Use String.equals(otherString)!

How does equals() method work in Java [duplicate]

This question already has answers here:
What is the difference between == and equals() in Java?
(26 answers)
Closed 9 years ago.
The equals method compares whether two object values are equal or not. My question is how it compares the two objects? How can it tell the two objects are equal or not? I want to know based on what it compares the two objects. I am not including the hashCode method.
The default implementation, the one of the class java.lang.Object, simply tests the references are to the same object :
150 public boolean equals(Object obj) {
151 return (this == obj);
152 }
The reference equality operator is described like this in the Java Specification :
At run time, the result of == is true if the operand values are both
null or both refer to the same object or array; otherwise, the result
is false.
This default behavior isn't usually semantically satisfying. For example you can't test equality of big Integer instances using == :
Integer a = new Integer(1000);
Integer b = new Integer(1000);
System.out.println(a==b); // prints false
That's why the method is overridden :
722 public boolean equals(Object obj) {
723 if (obj instanceof Integer) {
724 return value == ((Integer)obj).intValue();
725 }
726 return false;
727 }
which enables this :
System.out.println(a.equals(b)); // prints true
Classes overriding the default behavior should test for semantic equality, based on the equality of identifying fields (usually all of them).
As you seem to know, you should override the hashCode method accordingly.
Consider following example,
public class Employee {
String name;
String passportNumber;
String socialSecurityNumber;
public static void main(String[] args) {
Employee e1 = new Employee();
Employee e2 = new Employee();
boolean isEqual = e1.equals(e2); // 1
System.out.println(isEqual);
}
}
In the code at comment //1 it calls inherited equals method from Object class which is simply comparing references of e1 and e2. So it will always give false for each object created by using new keyword.
Following is the method excerpt from Object
public boolean equals(Object obj) {
return (this == obj);
}
For comparing equality check JLS has given equals method to override in our class. It is not final method. JLS doesn't know on what basis programmar wants to make two objects equal. So they gave non-final method to override.
hashcode does not play role to check object's equality. hashcode checks/finds the Bucket where object is available. we use hashcode in hashing technique which is used by some classes like HashMap..
If two object's hashcode are equals that doesn't means two objects are equal.
For two objects, if equals method returns true then hashcode must be same.
You will have to override equals method to decide on which basis you want object e1 and e2 in above code is equal. Is it on the basis of passportNumber or socialSecurityNumber or the combination of passportNumber+socialSecurityNumber?
I want to know based on what it compares the two objects.
Answer is, by default with the help of inherited Object class's equals method it compares two object's reference equality by using == symbol. Code is given above.
logically, equals does not compare objects (however you can do anything with it), it compares values. for object comparison there is '==' operator

What does equals(Object obj) do?

I´ve often found an equals method in different places. What does it actually do? Is it important that we have to have this in every class?
public boolean equals(Object obj)
{
if (obj == this)
{
return true;
}
if (obj == null)
{
return false;
}
if (obj instanceof Contact)
{
Contact other = (Contact)obj;
return other.getFirstName().equals(getFirstName()) &&
other.getLastName().equals(getLastName()) &&
other.getHomePhone().equals(getHomePhone()) &&
other.getCellPhone().equals(getCellPhone());
}
else
{
return false;
}
}
It redefines "equality" of objects.
By default (defined in java.lang.Object), an object is equal to another object only if it is the same instance. But you can provide custom equality logic when you override it.
For example, java.lang.String defines equality by comparing the internal character array. That's why:
String a = new String("a"); //but don't use that in programs, use simply: = "a"
String b = new String("a");
System.out.println(a == b); // false
System.out.println(a.equals(b)); // true
Even though you may not need to test for equality like that, classes that you use do. For example implementations of List.contains(..) and List.indexOf(..) use .equals(..).
Check the javadoc for the exact contract required by the equals(..) method.
In many cases when overriding equals(..) you also have to override hashCode() (using the same fields). That's also specified in the javadoc.
Different classes have different criteria for what makes 2 objects "equal". Normally, equals() returns true if it is the same Object:
Object a = new Object();
Object b = new Object();
return(a.equals(b));
This will return false, eventhough they are both "Object" classes, they are not the same instance. a.equals(a) will return true.
However, in cases like a String, you can have 2 different instances but String equality is based on the literal characters that make up those Strings:
String a = new String("example");
String b = new String("example");
String c = new String("another");
a.equals(b);
a.equals(c);
These are all different instances of String, but the first equals will return true because they are both "example", but the 2nd will not because "example" isn't "another".
You won't need to override equals() for every class, only when there is a special case for equality, like a class that contains 3 Strings, but only the first String is used for determining equality. In the example you posted, there could have been another field, description which could be different for 2 different "Contacts", but 2 "Contacts" will be considered equal if those 4 criteria match (first/last name, and home/cell phone numbers), while the description matching or not matching doesn't play into whether 2 Contacts are equal.
Aside from everything given by Bozho, there are some additional things to be aware of if overriding equals:
something.equals(null) must always return false - i.e. null is not equal to anything else. This requirement is taken care of in the second if of your code.
if it is true that something == something else, then also something.equals(something else) must also be true. (i.e. identical objects must be equal) The first if of your code takes care of this.
.equals SHOULD be symetric for non-null objects, i.e. a.equals(b) should be the same as b.equals(a). Sometimes, this requirement breaks if you are subclassing and overriding equals in the parent-class and in the subclass. Often equals contains code like if (!getClass().equals(other.getClass())) return false; that at least makes sure that a diffrent object type are not equal with each other.
If you override equals you also MUST override hashCode such that the following expression holds true: if (a.equals(b)) assert a.hashCode() == b.hashCode(). I.e. the hash code of two objects that are equal to each other must be the same. Note that the reverse is not true: two objects that have the same hash code may or may not be equal to each other. Ususally, this requirement is taken care of by deriving the hashCode from the same properties that are used to determine equality of an object.
In your case, the hashCode method could be:
public int hashCode() {
return getFirstName().hashCode() +
getLastName().hashCode() +
getPhoneHome().hashCode() +
getCellPhone().hashCode();
}
If you implement Comparable that compares two objects if they are smaller, larger, or equal to each other, a.compareTo(b) == 0 should be true if and only if a.equalTo(b) == true
In many IDEs (e.g. Eclipse, IntelliJ IDEA, NetBeans) there are features that generate both equals and hashCode for you, thereby sparing you of tedious and possibly error-prone work.
The equals method is used when one wants to know if two objects are equivalent by whatever definition the objects find suitable. For example, for String objects, the equivalence is about whether the two objects represent the same character string. Thus, classes often provide their own implementation of equals that works the way that is natural for that class.
The equals method is different from == in that the latter tests for object identity, that is, whether the objects are the same (which is not necessarily the same as equivalent).
It enables you to re-define which Objects are equal and which not, for example you may define that two Person objects as equal if the Person.ID is the same or if the Weight is equal depending on the logic in your application.
See this: Overriding the java equals() method quirk
By default, the Object class equals method invokes when we do not provide the implementation for our custom class. The Object class equals method compares the object using reference.
i.e. a.equals(a); always returns true.
If we are going to provide our own implementation then we will use certain steps for object equality.
Reflexive: a.equals(a) always returns true;
Symmetric: if a.equals(b) is true then b.equals(a) should also be true.
Transitive: If a.equals(b), b.equals(c) then a.equals(c) should be true/false according to previous 2 result.
Consistent: a.equals(b) should be the same result without modifying the values of a and b.
Note: default equals method check the reference i.e. == operator.
Note: For any non-null reference value a, a.equals(null) should return
false.
public class ObjectEqualExample{
public static void main(String []args){
Employee e1 = new Employee(1, "A");
Employee e2 = new Employee(1, "A");
// if we are using equals method then It should follow the some properties such as Reflexive, Symmetric, Transitive, and constistent
/*
Reflexive: a.equals(a) always returns true;
Symmetric: if a.equals(b) is true then b.equals(a) should also be true.
Transitive: If a.equals(b), b.equals(c) then a.equals(c) should be true/false according to previous 2 result.
Consistent: a.equals(b) should be the same result without modifying the values of a and b.
Note: default equals method check the reference i.e. == operator.
Note: For any non-null reference value a, a.equals(null) should return false
*/
System.out.println(e1.equals(e1));
System.out.println(e1.equals(e2));
}
}
class Employee {
private int id;
private String name;
#Override
public String toString() {
return "{id ="+id+", name = "+name+"} ";
}
#Override
public boolean equals(Object o) {
// now check the referenc of both object
if(this == o) return true;
// check the type of class
if(o == null || o.getClass() != this.getClass()) return false;
// now compare the value
Employee employee = (Employee)o;
if(employee.id == this.id && employee.name.equals(this.name)) {
return true;
} else return false;
}
public int hashCode() {
// here we are using id. We can also use other logic such as prime number addition or memory address.
return id;
}
public Employee(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
}
One more thing, maps use the equals method to decide if an Object is present as a key. https://docs.oracle.com/javase/8/docs/api/java/util/Map.html

Categories

Resources