Search code examples
javacomparatortreemap

Tree Map Comparator Function Overloading


I was trying to add a custom compartor to sort a map, Following is my comparator,

public static class MyComparator implements Comparator<String> {

    private String NAME_REGEX = "M\\d+";

    public int compare(String o1, String o2) { 

        if (o1.matches(NAME_REGEX) && o2.matches(NAME_REGEX)) {
            try {
                return Integer.parseInt(o1.substring(1)) - Integer.parseInt(o2.substring(1));
            } catch (NumberFormatException ex) {
                return o1.compareTo(o2);
            }
        } else {
            return o1.compareTo(o2);
        }
    }
}

And my usage is below,

public static void main(String[] args) {

    Map<String, String> map = new TreeMap<String, String>() { 
        @Override
        public Comparator<? super String> comparator() {
            return new MyComparator();
        }
    }; 

    map.put("M10", "data");
    map.put("M9", "data");
    map.put("M11", "data");
    map.put("M12", "data");
    map.put("M6", "data");

    for (String keys : map.keySet()) {
        System.out.print(keys);
    }
}

this code has no impact on the comparision mechanism of the treemap.

But when I pass MyComparator instance as constructor param, keys are sorted by using MyComparator.

Why the first approach failed?


Solution

  • When looking at the source of TreeMap.put, we see that it's referencing the comparator directly:

    public V put(K key, V value) {
        ...
        //cpr is the the comparator being used
        Comparator<? super K> cpr = comparator;
        ....
    }
    

    This means that it is not using your overridden comparator() method, and that explains why it doesn't work.