Do two equal objects have to have the same toString output? - java

Do two equal objects have to have the same toString output?
In code, does the following have to hold in general?
if(o1.equals(o2))
return o1.toString().equals(o2.toString()) // always true?
I am asking because I have just written a toString method for which the above statement does not hold. I could not find any hint at the documentation, but I want to get sure my toString method does not break any contract rules.

No, they do not have to have the same toString() output in order to be equal. There is no contract in Java that states the equals() method must be true for both the object itself and its toString() method.
The only contract equals() has with other methods is with hashCode():
Note that it is generally necessary to override the hashCode method whenever this method [equals] is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
The contract it has irrespective of other methods is:
It is reflexive: for any non-null reference value x, x.equals(x) should return true.
It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
For any non-null reference value x, x.equals(null) should return false.
Source: https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-
Edit: Some people are saying Effective Java by Joshua Bloch says the toString() method should use the same fields as the equals() method. This is not true. He states:
While it isn’t as important as obeying the equals and hashCode contracts (Item 8, Item 9), providing a good toString implementation makes your class much more pleasant to use.
What he classifies as a "good implementation" is:
When practical, the toString method should return all of the interesting information contained in the object, as in the phone number example just shown. It is impractical if the object is large or if it contains state that is not conducive to string representation. Under these circumstances, toString should return a summary such as “Manhattan white pages (1487536 listings)” or “Thread[main,5,main]”.
So no, it in no way relates to the equals() method.

There is no requirement for this. There is a dependency between equals and hashCode: equal objects must return the same hashCode value. toString is only used for printing the object.

There is no contract for toString, only for equals and hashCode. And from my point of view it also doesn't make sense.
Imagine o1 and o2 are of class Person{}, then you get only the string of the reference.

There's no "requirement" that hashCode match equals, only a best practice that it do so, or your program won't make sense. Same with toString. It should be consistent with equals, as should compareTo if used. See Effective Java by Joshua Bloch for the rationale. People who tell you otherwise need to read that book because they're mistaken.

Related

equals method usage in string and list

on the oracle java documentation,
equals() from list says two lists are defined to be equal if they contain the same elements.
But from object class equals() return true only if their hash code is equal.
It means equals() from list overrides equals method from object class. And it's same for equals() from string. As long as they have same characters, they return true.
so whenever I declare a type as String, or use list classes like arraylist
equals() are overriden automatically righT?
equals() are overridden automatically righT?
Answer : Yes absolutely right, If you are asking overriden .equals() method is invoked automatically at run time
**Object class is parent class for every class in java and it consist of .equals() method which compares the object references
But String class, Wrapper classes (Integer,Long etc..) and Collections Classes (ArrayList, hashSet etc..) are overridden .equals() method to compare content in object instead of object references
to avoid confusions here is the clear example
public class Main2 {
public static void main(String[] args) {
List<String> l1 = new ArrayList<>();
l1.add(new String("hello"));
List<String> l2 = new ArrayList<>();
l2.add(new String("hello"));
System.out.println(l1.equals(l2)); //true
List<Test> t1 = new ArrayList<>();
t1.add(new Test());
List<Test> t2 = new ArrayList<>();
t2.add(new Test());
System.out.println(t1.equals(t2)); //false
}
}
class Test{
}
In the above example comparing List<String> will return true because .euqals() method in String is overridden to compare content
But while comparing Lits<Test> will return false even though both objects are empty, since .equals() method in Test class is not overridden by default it will invoke Object class .equals() method which compares reference of objects as == does
Google Question object class equals method compares hashcode ?
Answer
The java.lang.Object class requires that any two objects that compare equal using the equals() method must produce the same integer result when the hashCode() method is invoked on the objects [API 2014]. The equals() method is used to determine logical equivalence between object instances.Feb 12, 2018
equals() are overriden automatically righT?
No. Methods are not overwritten "automatically".
You can look at the code - both classes have their own implementation of equals and hashCode. This implementation is what is used at runtime. If you're writing your own class, you will likely implement equals and hashCode.
But from object class equals() return true only if their hash code is equal.
I think you (and the original version of the other answer) are misunderstanding the documentation on equals:
Indicates whether some other object is "equal to" this one.
The equals method implements an equivalence relation on non-null object references:
It is reflexive: for any non-null reference value x, x.equals(x) should return true.
It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
For any non-null reference value x, x.equals(null) should return false.
The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).
Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
The only part of this that refers to hashCode is at the end, which specifies that equal objects must have equal hash codes - this isn't automatic, it's by convention so things like HashMap will work.
Comparing hashCode values is NOT the default implementation of equals, and should NEVER be the implementation of equals - it is possible to have multiple non-equal objects with the same result for hashCode. The rule is to make sure your hashCode implementation returns the same value if objects are equal.
As an example, both of these will output the same hashCode, but are clearly not equal:
System.out.println("Aa".hashCode());
System.out.println("BB".hashCode());
Recommended further reading: this related question.
No, .equals() would not magically get overwritten when String are getting compared in list.
the String Class in java already has the .equals() method overwritten in its definition to compare characters by default.
meaning, even without a list if you do this:
String a = new String("abc");
String b = new String("abc");
System.out.println(a.equals(b));
Then, your output would be true
refer this: https://docs.oracle.com/javase/7/docs/api/java/lang/String.html

More on equals and hashCode

I understand the contract between the equals and hashCode methods. If equals is overridden, hashCode should also be. Can I override the hashCode method to always return the same value, say the int 23? Can I override the hashCode method to return a random number each time it is called?
You shouldn't override hashCode to return a random value. It should always return the same value for the same instance.
This is clearly stated in the Javadoc :
Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified.
You shouldn't return a constant value, since it would make a very poor hashCode when used in classes such as HashMap and HashSet.
This is also mentioned in the Javadoc :
It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

Can I implement hashCode and equals this way for (Hash)Sets?

I know that if a.equals(b), we must have a.hashCode() == b.hashCode() else we get strange results, but I'm wondering if the converse is also required.
More specifically, I have a hashCode() function that uses the field id to calculate the hashCode. However, my equals() function only uses the simple comparison "==" to check for equality. This may seem strange but unless more details are required, it's simply how I've implemented it.
Now the question is will this mess anything up? Specifically for HashSets, but more generally, for any (common) implementations of Set.
The way I understand it, a Set will first check the hashCode then the equals operator to see if a duplicate object exists. In this case, it should work right? If two objects are the same instance, they will produce the same hashCode as well as return true for equals() and thus the Set will only allow the instance to be be added once.
For two separate instances with the same id, the hashCode will be identical but then the equals() operator will return false and thus allow both objects to enter the Set, which is what I hope to accomplish.
Is this a beginner's mistake? Am I missing something? Will this have an unexpected results for any collection types other than Set?
edit:
I guess I should explain myself. I have a Hibernate object FooReference which implements both a hashCode and equals method using the id. This object is guaranteed to always have a unique id. However, before this object is persisted, I use a Foo object which has a default id of -1. So when putting it in a Set (to be saved) I know each Foo is unique (thus the basic == operator). So this Foo which extends FooReference overrides the equals method with a basic ==. For my purposes this should work... hopefully.
Objects are allowed to have the same hashcode without being equal to each other. In fact, it's perfectly valid (though inefficient and a bad idea) to implement hashCode as simply return 0, giving every instance the same hashcode.
All that's required is that if two objects are equal (as determined by the equals method), they have the same hashcode.
However, if your equals method just compares the two objects using == internally, no two (distinct) instances will ever be equal to each other, so there's no point defining your own hashCode and equals methods at all. The default implementations will produce the same behavior.

myArralist.contains(obj) always return false though myArraylist contain specified obj in java?

I am trying to check wether mylist contains a given object or not, where mylist is an ArrayList of type myCustomClass.
If you add an instance of MyCustomClass to the list, and then check if it contains another instance of MyCustomClass, it will always return false, unless you override the equals method in your custom class. The equals method checks if another object is functionally equal to this object.
Make sure to override the hashCode method each time you override the equals method. hashCode should return the same value for two equal objects. Also, equals should be written so that it's symmetric: a.equals(b) if and only if b.equals(a).
Check equals and hashCode in the javadoc of java.lang.Object.
You most likely haven't implemented equals() and hashcode() on myCustomClass. You need to implement them properly and according to contract, see here for details of how.

equals() and operator "==" in java

I know that equals() will compare the value of objects, the '==' operator will check if the variable point to the same memory.
I do not understand how equals() compare the value of objects, for example:
class Test {
public Test(int x, float y) {
this.x = x;
this.y = y;
}
int x,
float y;
}
Test test1 = new Test(1,2.0);
Test test2 = new Test(1,2.0);
So if I use equals(), will it compare each properties in each object?
And what about if we are talking about String? using equals() and operator “==”, do we still need to override the equals()?
No, if you don't override the equals-method in your class, then equals is the same as ==. See the documentation for this:
The equals method for class Object
implements the most discriminating
possible equivalence relation on
objects; that is, for any non-null
reference values x and y, this method
returns true if and only if x and y
refer to the same object (x == y has
the value true).
The documentation also states what requirements there are for equals methods in case you want to implement it.
Not unless you overload it properly according to the rules laid down by Joshua Bloch.
The default behavior checks equality of references using ==.
It's important to override equals and hashCode for your objects, especially if you intend to use them in java.util.Collections.
The equals method is defined in class Object, and since all objects in Java implicitly or explicitly inherit from this class, they too will inherit the equals() method as implemented by Object. The default implementation in Object will simply return true if the objects pass the "==" condition.
However, you are free to override the equals() method in your own class and specify the criteria which must be checked to see if two objects are meaningfully equal. For example, you might say that two instances are only equal if each of its attributes contain the same values as another object, or you might instead want to simply check a few attributes which make up the objects "business key" and ignore the others.
The equality of String classes follow the same rules as any other class in Java; "==" will be true if they do refer to the same instance, and equals() will be true if they contain the same values.

Categories

Resources