简体   繁体   中英

Why AbstractCollection does not implement equals()?

Did you know that :

Map<Object,Object> m1 = new HashMap<Object, Object>();
Map<Object,Object> m2 = new HashMap<Object, Object>();
System.out.println("m1.equals(m2) = "+m1.equals(m2));
System.out.println("m1.keySet().equals(m2.keySet()) = "
            +m1.keySet().equals(m2.keySet()));
System.out.println("m1.entrySet().equals(m2.entrySet()) = "
            +m1.entrySet().equals(m2.entrySet()));
System.out.println("m1.values().equals(m2.values()) = "
            +m1.values().equals(m2.values()));

would output :

m1.equals(m2) = true
m1.keySet().equals(m2.keySet()) = true
m1.entrySet().equals(m2.entrySet()) = true
m1.values().equals(m2.values()) = false

This is caused by the fact that AbstractCollection (which HashMap$Values inherits from) does not overrides #equals() .

Do you have an idea why this is so ?

Per the contract of Collection#equals() , there is no general-purpose equals() methods for Collection s, and thus AbstractCollection cannot provide one.

Note that HashMap$Values is neither a Set nor a List, thus the quandary and in a sense the reason it does not support equals() .

Both AbstractList and AbstractSet extend AbstractCollection, and they have different behaviors for their equals() methods, specified by the interfaces List and Set . The interface for Collection says:

While the Collection interface adds no stipulations to the general contract for the Object.equals, programmers who implement the Collection interface "directly" (in other words, create a class that is a Collection but is not a Set or a List) must exercise care if they choose to override the Object.equals.

So AbstractCollection should definitely not override equals(). That said, I don't really know why HashMap$Values would not implement equals() itself.

I am not sure if thatt's the official reason, but AbstractCollection avoids adding semantic constraints on potential subclasses. The semantics of equality are determined by the nature of the concrete inheriting data structure, and in particular based on whether your structure is ordered and whether it allows duplicates.

For example, Consider TreeSet, LinkedList, Bag, etc.

BTW, In relation to the code you posted, what's the actual type of whatever is returned by values? That should be a subclass with a concrete implementation.. If your map is empty when you run this code, it's possible that you would be ending up with something that does not consider two empty sets equal.

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