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<String, Integer>的排序開始,其他類型可自行替換

在JDK8 以前,一般都是這樣寫:

    public static void main(String[] args) {
        //這裏自定義一個需要排序的map集合
        Map<String, Integer> map = new HashMap<String, Integer>();
        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<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)
                return o1.getValue().compareTo(o2.getValue());
            };
        });
        for (Entry<String, Integer> 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<String, Integer> map = new HashMap<String, Integer>();
        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<String> 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<String, Integer> map = new HashMap<String, Integer>();
        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<String> 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<String, Integer> map = new HashMap<String, Integer>();
        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<String> 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<String, Integer>::getValue):顧名思義,就是此處的比較規則,Map.Entry中有getKey(),getValue()等方法,通過改變取值,就可以改變排序對象,而默認排序爲自然排序,reversed():該方法將 其改變爲倒序;
4、map(Map.Entry<String, Integer>::getKey):此處將Entry<String, Integer>中的key單獨抽離出來;
5、collect(Collectors.toList()):告訴程序返回的是一個List集合;


全文到此,對JDK1.8中的新特性還不熟悉的仔仔們,可以去看一些相關文檔,預計下一篇爲:《List集合排序——彙總》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章