In Java, sort hash map by its key.length()

2019-04-27 18:19发布

i have a hashmap like this:

HashMap<String,Integer> map = new HashMap<String,Integer>();
map.put("java",4);
map.put("go",2);
map.put("objective-c",11);
map.put("c#",2);

now i want to sort this map by its key length, if two keys length are equal (e.g go and c# both length 2), then sorted by alphba order. so the outcome i expect to get is something like:

printed result: objective-c, 11 java, 4 c#, 2 go, 2

here is my own attamp, but it doesnt work at all...

      HashMap<String,Integer> map = new HashMap<String,Integer>();
          map.put("java",4);
          map.put("go",2);
          map.put("objective-c",11);
          map.put("c#",2);

      Map<String,Integer> treeMap = new TreeMap<String, Integer>(
                new Comparator<String>() {
                    @Override
                    public int compare(String s1, String s2) {
                        return s1.length().compareTo(s2.length());
                    }
                }
        );

actually the 'compareTo' method appears as red (not be able to compile).... please someone help me with some code example...i am a bit confusing with how to use comparator class to customize compare object...

6条回答
The star\"
2楼-- · 2019-04-27 18:45

because length() doesn't define compareTo method thats why you see error. To correct it use Integer.compare(s1.length(), s2.length()); updated code below

import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class Test {

    public static void main(String[] args) {

        HashMap<String,Integer> map = new HashMap<String,Integer>();
        map.put("java",4);
        map.put("go",2);
        map.put("objective-c",11);
        map.put("c#",2);


        Map<String,Integer> treeMap = new TreeMap<String, Integer>(
                new Comparator<String>() {
                    @Override
                    public int compare(String s1, String s2) {
                        return Integer.compare(s1.length(), s2.length());
                    }
                }
        );

        treeMap.putAll(map);

        System.out.println(treeMap);
    }
}
查看更多
Fickle 薄情
3楼-- · 2019-04-27 18:49

The compiler is complaining because you cannot call compareTo on an int. The correct way to sort the map is the following:

Map<String, Integer> treeMap = new TreeMap<String, Integer>(
    new Comparator<String>() {
        @Override
        public int compare(String s1, String s2) {
            if (s1.length() > s2.length()) {
                return -1;
            } else if (s1.length() < s2.length()) {
                return 1;
            } else {
                return s1.compareTo(s2);
            }
        }
});

The first two conditions compare the lengths of the two Strings and return a positive or a negative number accordingly. The third condition would compare the Strings lexicographically if their lengths are equal.

查看更多
爷、活的狠高调
4楼-- · 2019-04-27 18:50

The Comparator should be:

new Comparator<String>() {
    @Override
    public int compare(String s1, String s2) {
        return Integer.compare(s1.length(), s2.length());
    }
}
查看更多
爷的心禁止访问
5楼-- · 2019-04-27 18:55
        public int compare(String o1, String o2) {
            return o1.length() == o2.length() ? o1.compareTo(o2) : o1.length() - o2.length();
        }
查看更多
仙女界的扛把子
6楼-- · 2019-04-27 18:56

If using the TreeMap is not mandatory

Explantion: Define a Comaprator , and next step, define a list so we can add all map entries into a list. At the end, sort the list by defined Comaprator

Code:

 Comparator<Map.Entry<String,Integer>> byMapValues = 
         (Map.Entry<String,Integer> left, Map.Entry<String,Integer> right) ->left.getValue().compareTo(right.getValue());

 List<Map.Entry<String,Integer>> list = new ArrayList<>();
 list.addAll(map.entrySet());
 Collections.sort(list, byMapValues);
 list.forEach( i -> System.out.println(i));

Output:

c#=2
go=2
java=4
objective-c=11

Note: get sorted by number

if there is need to do comparison based on key, the following line can be used.

Comparator<Map.Entry<String,Integer>> byMapKeys = 
             (Map.Entry<String,Integer> left, Map.Entry<String,Integer> right) -> left.getKey().compareTo(right.getKey());
查看更多
不美不萌又怎样
7楼-- · 2019-04-27 18:58

You call String#length(), which returns a primitive int. You need the static method Integer.compare(int,int). If you are on Java 8, you can save yourself a lot of typing:

Map<String,Integer> treeMap = new TreeMap<>(
        Comparator.comparingInt(String::length)
                  .thenComparing(Function.identity()));
查看更多
登录 后发表回答