I think I may have found a bug in Java.
I have a TreeMap in which I use a custom comparator. However, it seems when I put(key, value), on a key that already exists, it does not override the key, thus creating duplicate keys. I think I have verified this because I tried:
System.out.println(testMap.firstKey().equals(testMap.lastKey()));
And this prints out true. Anyone know why this is happening?
This is the comparator code:
private class TestComp implements Comparator {
@Override
public int compare(String s1, String s2){
if (s1.equals(s2)) {
return 0;
}
int temp = otherMap.get(s1).compareTo(otherMap.get(s2));
if (temp > 0) {
return 1;
}
return -1;
}
解决方案
A comparator always needs to return consistent results, and when used in a TreeMap, be consistent with equals.
In this case your comparator violates the first constraint since it does not necessarily give consistent results.
Example: If for instance otherMap maps
"a" -> "someString"
"b" -> "someString"
then both compare("a", "b") and compare("b", "a") will return -1.
Note that if you change the implementation to
if (s1.equals(s2)) {
return 0;
}
return otherMap.get(s1).compareTo(otherMap.get(s2));
you break the other criteria of being consistent with equals, since otherMap.get(s1).compareTo(otherMap.get(s2)) might return 0 even though s1 does not equal s2.
I've elaborated on this in a self-answered follow up question here.
From the comments:
Even if a comparator gives inconsistent results, shouldn't the Java language still not allow duplicate keys?
No, when you insert a key, the TreeMap will use the comparator to search the data structure to see if the key already exists. If the comparator gives inconsistent results, the TreeMap might look in the wrong place and conclude that the key does not exist, leading to undefined behavior.