简体   繁体   中英

TreeSet not adding all elements and HashSet

I have two sets on my code, and on them I add the same collection of elements. The problem is, the TreeSet doesn't add all elements. I am getting a bit confused.

I having a problem for a while now and I am struggling to find out why my TreeSet won't add all of the elements in the Collection I pass to addAll.

It is a TreeSet build with a comparator, for items that have an equals method like:

public final boolean equals(Object o) {
    return this==o;
}

@Override
public int hashCode() {
    int hash = 3;
    hash = 67 * hash +     Objects.hashCode(this.grauDeAdaptacao);
    hash = 67 * hash + Objects.hashCode(this.idade);
    return hash;
}

Just to test I did the following:

HashSet<Item> test1 = new HashSet<>(items);
TreeSet<Item> test2 = new TreeSet<>(getComparator());
test2.addAll(items);
if (test1.size() < 50 || test2.size()<50 ) {
    throw new IllegalStateException();
}

And the comparator uses:

private int compare(S ser1, S ser2) {
    return ser1.getGrau().compareTo(ser2.getGrau());
}

But what is awkward is that, the hash seams fine, while the TreeSet don't have all 50 elements.

I need two elements to be equal just when they are the same instance, in all subclasses, that is why I made the final method like that.

A HashSet uses equals to test two objects for equality.

A HashSet guarantees that it is never the case that for any two distinct objects, a and b , in the Set a.equals(b) == true .

A TreeSet uses compareTo to test two objects for equality.

A TreeSet guarantees that it is never the case that for any two distinct objects, a and b , in the Set a.compareTo(b) == 0 .

Under the assumption that a.compareTo(b) == 0 iff a.equals(b) then this behaviour is the same. Under this condition it can be said that the compareTo method is "consistent with equals ", as defined in the documentation for Comparable

The same documentation also states that:

It is strongly recommended (though not required) that natural orderings be consistent with equals. This is so because sorted sets (and sorted maps) without explicit comparators behave "strangely" when they are used with elements (or keys) whose natural ordering is inconsistent with equals. In particular, such a sorted set (or sorted map) violates the general contract for set (or map), which is defined in terms of the equals method.

This is an example of 'behav[ing] "strangely"'.

You have some objects for which a.equals(b) == false but a.compareTo(b) == 0 .

It should further be noted that the for the implementation of hashCode it is required that if a.equals(b) == true then a.hashCode() == b.hashCode() . This is not the case in your implementation. Your implementation of hashCode() is invalid given your implementation of equals .

The reflexive property is not required. ie it can (and will) be the case that a.hashCode() == b.hashCode() and a.equals(b) == false .

So, in summary.

  1. Your hashCode and equals are wrong. They need to be consistent, as described in the documentation for equals and hashCode .
  2. Your comapreTo is wrong, it should be "consistent with equals " as described in the documentation for Comparable .

Solved, with your help of course. As I needed a data structure that as efficient to insert and search, while it would be always sorted - beening from the Java SE API. TreeSet was just too simple to not use it. So I adjusted the comparator and the items to use IDs. and just like that the Tree got happy, it ordered my elements with the property I intended, and in case they were the same, the ID would decide the order...it got compatible with equals, and everybody got happy.

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