Map集合排序——根据value对key进行排序

Map集合排序——根据value对key进行排序

在流水的业务中,码出最优雅的代码。

描述:有若干个键值对格式的json字符串,根据其中的value进排序,取出其中的排位靠前的一半以上的key值,json数据为:{“1.B.1.f”:”1.8”,”1.B.1.e”:”2.5”,”1.B.1.b”:”3.0”,”1.B.1.d”:”3.0”,”1.B.1.a”:”3.5”,”1.B.1.c”:”2.3”},这是业务上的一个需求,于是针对这个需求就有了对Map的排序一系列探索


前言:对于json转Map本篇就不介绍,直接从对Map的排序开始,其他类型可自行替换

在JDK8 以前,一般都是这样写:

    public static void main(String[] args) {
        //这里自定义一个需要排序的map集合
        Map map = new HashMap();
        map.put("1.B.1.c", 45);
        map.put("1.B.1.d", 65);
        map.put("1.B.1.a", 12);
        map.put("1.B.1.b", 15);
        map.put("1.B.1.e", 78);
        int size = map.size();
        // 通过map.entrySet()将map转换为"1.B.1.e=78"形式的list集合
        List> list = new ArrayList>(size);
        list.addAll(map.entrySet());
        // 通过Collections.sort()排序
        Collections.sort(list, new Comparator>() {
            public int compare(Map.Entry o1, Map.Entry o2) {
                // compareTo方法 (x < y) ? -1 : ((x == y) ? 0 : 1)
                return o1.getValue().compareTo(o2.getValue());
            };
        });
        for (Entry entry : list){
            // 得到排序后的键值
            System.out.println(entry.getKey());
        }
    }

有时候我们会想,把这个方法提炼出来,放在一个工具类中,如是我们将会这样做:

    public static List<String> sortMapByValue(Map<String, Integer> map){  
        int size = map.size();  
        //通过map.entrySet()将map转换为"1.B.1.e=78"形式的list集合
        List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(size);
        list.addAll(map.entrySet());
        //通过Collections.sort()排序
        Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                // compareTo方法 (x < y) ? -1 : ((x == y) ? 0 : 1)
                // 倒序:o2.getValue().compareTo(o1.getValue())
                // 顺序:o1.getValue().compareTo(o2.getValue())
                return o2.getValue().compareTo(o1.getValue());
            };
        }); 
        List<String> keys = new ArrayList<String>(size);  
        for (Entry<String, Integer> entry : list){
            // 得到排序后的键值
            keys.add(entry.getKey());
        }
        return keys;      
    }  
    public static void main(String[] args) {
        //这里自定义一个需要排序的map集合
        Map map = new HashMap();
        map.put("1.B.1.a", 45);
        map.put("1.B.1.e", 65);
        map.put("1.B.1.c", 12);
        map.put("1.B.1.b", 15);
        map.put("1.B.1.d", 78);
        List keys = sortMapByValue(map);
        for (String key : keys){
            System.out.println(key);
        }
    }

看起来好像有点复杂,而且实现Comparator接口的比较器好像可以抽离出来,其他地方也可以复用,于是:

    public static List<String> sortMapByValue(Map<String, Integer> map) {
        int size = map.size();
        //通过map.entrySet()将map转换为"1.B.1.e=78"形式的list集合
        List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(size);
        list.addAll(map.entrySet());
        //通过Collections.sort()排序
        Collections.sort(list, new ValueComparator());
        List<String> keys = new ArrayList<String>(size);
        for (Entry<String, Integer> entry : list){
            // 得到排序后的键值
            keys.add(entry.getKey());
        }
        return keys;
    }

    private static class ValueComparator implements Comparator<Map.Entry<String, Integer>> {
        public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
            // compareTo方法 (x < y) ? -1 : ((x == y) ? 0 : 1)
            // 倒序:o2.getValue().compareTo(o1.getValue()),顺序:o1.getValue().compareTo(o2.getValue())
            return o2.getValue().compareTo(o1.getValue());
        }
    }

    public static void main(String[] args) {
        //这里自定义一个需要排序的map集合
        Map map = new HashMap();
        map.put("1.B.1.a", 45);
        map.put("1.B.1.e", 65);
        map.put("1.B.1.c", 12);
        map.put("1.B.1.b", 15);
        map.put("1.B.1.d", 78);
        List keys = sortMapByValue(map);
        for (String key : keys){
            System.out.println(key);
        }
    }

好像这样看起来简洁多了,而且还多了一个可复用的东西,但是,这样在JDK1.8中还远远不够。

在JDK1.8中是这样写的

    public static List<String> sortMapByValue(Map<String, Integer> map) {
        int size = map.size();
        //通过map.entrySet()将map转换为"1.B.1.e=78"形式的list集合
        List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(size);
        list.addAll(map.entrySet());
        List<String> keys = list.stream()
                .sorted(Comparator.comparing(Map.Entry<String, Integer>::getValue).reversed())
                .map(Map.Entry<String, Integer>::getKey)
                .collect(Collectors.toList());
        return keys;
    }

    public static void main(String[] args) {
        //这里自定义一个需要排序的map集合
        Map map = new HashMap();
        map.put("1.B.1.a", 45);
        map.put("1.B.1.e", 65);
        map.put("1.B.1.c", 12);
        map.put("1.B.1.b", 15);
        map.put("1.B.1.d", 78);
        List keys = sortMapByValue(map);
        keys.forEach(System.out::println);
    }

惊不惊喜,意不意外。

在JDK 1.8中新增了函数式编程,对上述代码的解释为:
1、先将list集合转换为流,即:list.stream(),值得注意的是:在stream()中所做的任何操作都不会影响到原集合;
2、sorted() 方法:对list集合进行排序,具体见下一篇专门针对List排序的介绍;
3、Comparator.comparing(Map.Entry::getValue):顾名思义,就是此处的比较规则,Map.Entry中有getKey(),getValue()等方法,通过改变取值,就可以改变排序对象,而默认排序为自然排序,reversed():该方法将 其改变为倒序;
4、map(Map.Entry::getKey):此处将Entry中的key单独抽离出来;
5、collect(Collectors.toList()):告诉程序返回的是一个List集合;


全文到此,对JDK1.8中的新特性还不熟悉的仔仔们,可以去看一些相关文档,预计下一篇为:《List集合排序——汇总》

你可能感兴趣的:(知识点,java,map)