Search code examples
javacomparatorspring-framework-beans

Java Spring Comparator for TreeMap


I was trying to use a SortedMap with customized comparator in one of my spring project. It is a SortedMap, where i trying to sort by the second half of the string(which is the key). A example of the key "A:123".

I added a customized comparator to make sure SortedMap is go by the Integer order instead of String order.

Here is a simplified sample code, I have class with SortedMap inside:

class TestObject{
    private SortedMap<String, String> myMap = new TreeMap<String, String>({
            new Comparator<String>()
            {
                @Override
                public int compare(String s1, String s2)
                {
                       int m1 = Integer.parseInt(O1.split(":")[1]);
                       int m2 = Integer.parseInt(O2.split(":")[1]);
                       return m1- m2;
                } 
   });    
    void setMap(SortedMap<String, String> maps){
         myMap = maps;
    }    
    void getMap(){ return myMaps; }
}

And inside my main function I did:

class UpperClass{
  @Autowired
  TestObject object1;    
  public setNewMap(){
      SortedMap<String, String> myInput = new TreeMap<String, String>({
              //my comparator
      });
      myInput.put("A:10000", "XXX");
      myInput.put("A:500","XXX");
      myInput.put("A:200","XXX");
      object1.setMap(myInput);
 }
      pubic getResult(){
          SortedMap<String, String> result = object1.getMap();
      }    
}

So I remote debugger my application. It appears the comparator inside the class definition never got invoked. I print line by line, and myInput maintained the order of the string by output:

A:200
A:500
A:10000

However, when my application called get Result, it print out:

A:10000
A:200
A:500

which is the character order. So I wonder if I did something wrong by putting a comparator inside the class definition.


Solution

  • Your syntax is incorrect. The way to do it, with lambdas:

    new TreeMap<String, String>((a, b) -> a.length() - b.length());
    

    with Comparator's utility methods:

    new TreeMap<String, String>(Comparator::comparingInt(String::length));
    

    old style:

    new TreeMap<String, String>(new Comparator<String>() {
        public int compare(String a, String b) {
            return a.length - b.length;
    });
    

    the second one (using Comparator's utilities) is definitely the best of the three. Note you can chain (to represent: Sort first on this thing, and if those are the same, then on this thing, but in reverse: You can do that).