Home > Net >  Method compare() removed entries having same value in Java
Method compare() removed entries having same value in Java

Time:11-04

I am trying to create a sorted map using TreeMap<String, Integer> from an existing map in java.

Entries should be sorted based on value, so I created a custom Comparator.

class ValueComparator implements Comparator<String> {
    Map<String, Integer> base;
    ValueComparator(Map<String, Integer> base) {
        this.base = base;
    }
    @Override
    public int compare(String o1, String o2) {
        return base.get(o2).compareTo(base.get(o1));
    }
}

class Test {

    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("a", 100);
        map.put("b", 100);
        map.put("c", 200);
        map.put("d", 300);
        map.put("e", 400);
        SortedMap<String, Integer> sortedMap = new TreeMap<>(new ValueComparator(map));
        sortedMap.putAll(map);
        System.out.println(map);
        System.out.println(sortedMap);
    }
}

Output

{a=100, b=100, c=200, d=300, e=400}
{e=400, d=300, c=200, a=100}

As you can see, my sortedMap has removed one key having the same value. Can someone explain this? And how can we fix this?

CodePudding user response:

According to the Comparator you've provided, Strings "a" and "b" are duplicates because both of them are associated with value of 100. Hence, one or the other has to be rejected.

Note that base.get(o2).compareTo(base.get(o1)) would raise a NullPointerException if either o1 or o2 are not present in the base map.

Something along these lines would be safer:

Objects.compare(
    base.get(o2), base.get(o1), 
    Comparator.nullsFirst(Comparator.naturalOrder())
);

CodePudding user response:

You are missing the ordinal for dupes. Use it like this:

public int compare(String o1, String o2) {
    int val = base.get(o2).compareTo(base.get(o1));
    return val == 0 ? o1.compareTo(o2) : val;
}
  • Related