I was checking headMap method of TreeMap which returns a portion of Map whose keys are strictly less than toKey. So I was expecting output to be B, C but it returns only B. Here is a thing I did weird I changed compareTo method like this return this.priority > o.priority ? 1 : -1;
then it started returning C, B which is I was expecting. I am sure this is not correct but how can I get both B, C which has lower priority than A. Where I am getting it wrong. Thanks.
NavigableMap<PolicyTypePriorityWrapper, String> treeMap = new TreeMap();
PolicyTypePriorityWrapper a = new PolicyTypePriorityWrapper("A", 2);
PolicyTypePriorityWrapper b = new PolicyTypePriorityWrapper("B", 1);
PolicyTypePriorityWrapper c = new PolicyTypePriorityWrapper("C", 1);
treeMap.put(a, "A");
treeMap.put(b, "B");
treeMap.put(c, "C");
NavigableMap<PolicyTypePriorityWrapper, String> map = treeMap.headMap(a, false);
Set<PolicyTypePriorityWrapper> policyTypePriorityWrappers = map.keySet();
for (PolicyTypePriorityWrapper pol: policyTypePriorityWrappers) {
System.out.println(pol.getPolicyType());
}
PolicyTypePriorityWrapper.java
class PolicyTypePriorityWrapper implements Comparable<PolicyTypePriorityWrapper> {
private String policyType;
private int priority;
public PolicyTypePriorityWrapper(final String policyType, final int priority) {
this.policyType = policyType;
this.priority = priority;
}
public String getPolicyType() {
return this.policyType;
}
public int getPriority() {
return this.priority;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PolicyTypePriorityWrapper that = (PolicyTypePriorityWrapper) o;
if (priority != that.priority) return false;
return policyType.equals(that.policyType);
}
@Override
public int hashCode() {
int result = policyType.hashCode();
result = 31 * result + priority;
return result;
}
@Override
public int compareTo(final PolicyTypePriorityWrapper o) {
return Integer.compare(this.priority, o.priority);
}
}
That's because you are not following JDK documentation guidelines, from Comprarable
:
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.
As you can see you have circumstances in which a.compareTo(b) == 0
but !a.equals(b)
. Both "B", 1
and "C", 1
are considered equal for the TreeMap
:
Note that the ordering maintained by a tree map, like any sorted map, and whether or not an explicit comparator is provided, must be consistent with equals if this sorted map is to correctly implement the
Map
interface. (See Comparable or Comparator for a precise definition of consistent with equals.) This is so because theMap
interface is defined in terms of the equals operation, but a sorted map performs all key comparisons using itscompareTo
(or compare) method, so two keys that are deemed equal by this method are, from the standpoint of the sorted map, equal. The behavior of a sorted map is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Map interface.For example, if one adds two keys a and b such that
(!a.equals(b) && a.compareTo(b) == 0)
to a sorted set that does not use an explicit comparator, the second add operation returns false (and the size of the sorted set does not increase) because a and b are equivalent from the sorted set's perspective.
So what happens is that you compareTo
is not able to distinguish two elements with same priority but different type, but since a TreeMap is using ONLY that method to decide if two elments are equal then you are not adding them both to the map in the first place.
Did you try if treeMap.size() == 3
? My guess is that it's 2 in the first place.