简体   繁体   中英

Why does not Java HashSet.equals() check for object equality?

I've come to this phenomenon this morning, the equals method in Set does not check for value equality of the element while List does. This is not in accordance with the java doc.

Set<MyClass> s1 = new HashSet<>();
Set<MyClass> s2 = new HashSet<>();
Set<MyClass> s3 = new HashSet<>();
Set<MyClass> s4 = new HashSet<>();
List<MyClass> l1 = new ArrayList<>();
List<MyClass> l2 = new ArrayList<>();

MyClass o1 = new MyClass();
MyClass o2 = new MyClass();

// **this gives false, and does not call MyClass.equals().**
s1.add(o1);
s2.add(o2);
boolean setCompareWithDifferentObjects = s1.equals(s2);

// this gives true, and also does not call MyClass.equals().
s3.add(o1);
s4.add(o1);
boolean setCompareWithSaveObjects = s3.equals(s4);

// this give true, and MyClass.equals() is called.
l1.add(o1);
l2.add(o2);
boolean listCompare = l1.equals(l2)

I've done some research. According to this Java doc for Set , HashSet equals , HashSet containsAll , HashSet contains , it will use (o==null ? e==null : o.equals(e)) to check whether the elements are equal. So why is this happen? Can anyone give me some hint on this?

Thanks!

----------Answer to this question can be found here -----------

What issues should be considered when overriding equals and hashCode in Java?

I overrided equals() but not hashCode()...

btw, the same set comparison worked in groovy, even if hashCode() is not overriden.

HashSet includes a number of optimizations that can explain all of this: first, if two objects are put into different buckets by their hash codes, or if they have different hash codes at all, they may skip the equals call. This is allowed by the contract of Object.hashCode ; if two objects have different hash codes then they are not allowed to .equals to each other.

For the other case, HashSet takes advantage of the contract of .equals that specifies that if two objects are == to each other, then they must be .equals to each other. Part of HashSet 's implementation here checks if the elements are == , and if they are, it skips calling .equals .

If every method implements its contract correctly, this cannot change the semantics; HashSet will always behave exactly as if .equals were being called.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM