Java基础之Map集合排序

本文详细介绍了如何对Map集合按键和值进行排序,包括使用普通排序、TreeMap以及JDK8的Stream API实现升序和降序排列。通过转换为Set、List集合,自定义比较器以及利用Map.Entry接口的排序器进行排序,提供了多种实用的方法示例。
摘要由CSDN通过智能技术生成

一、概述

在我们实际的开发环境中,我们经常需要对Map集合按照键或者值进行排序,有时需要升序,有时又需要降序,为此笔者将自己平常使用的常见排序方法列出,以供大家参考,如有说的不对之处还望各位看官多多指教;

二、使用

1、按键排序
首先来说按照键排序,一般来说,解决该问题的思路可以归纳为以下几种:

① 将Map集合转成TreeMap集合实现排序,可降序、升序,如下方法ordnarySortByTreeMap所示;

② 将Map集合转化成对应的Set集合,List集合,遍历List集合,最后将所有排序后的元素填充到一个新的Map集合中,例如以下方法ordnarySortByKey所示;

③ 将Map集合转化成Set集合。利用jdk8中的Stream进行排序,可利用Map.Entry中的排序器进行排序,具体操作如方法newSortByKey所示,该方法与其他的方法相比,最大的亮点就是优雅且可以支持多种排序功能;

   /**
     * @describtion: 按照键的普通排序
     * @author: Sundz
     * @date: 2020/1/2 22:15
     * @param: [paramMap, isdesc] 入参集合  指定升序、降序
     * @return: java.util.Map<java.lang.String ,java.lang.Integer>
     */
    public static Map<String, Integer> ordnarySortByKey(Map<String, Integer> paramMap, boolean isdesc) {
        Preconditions.checkNotNull(paramMap);
        Set<Map.Entry<String, Integer>> sortedSet = paramMap.entrySet();
        Preconditions.checkNotNull(sortedSet);
        Map<String, Integer> resMap = new LinkedHashMap<>(paramMap.size());
        List<Map.Entry<String, Integer>> sortedList = Lists.newArrayList(sortedSet);
        //实现比较器
        Comparator<Map.Entry<String, Integer>> comparator = new Comparator<Map.Entry<String, Integer>>() {
            @Override
            public int compare(Map.Entry<String, Integer> entry1, Map.Entry<String, Integer> entry2) {
           		//也可采用entry2比较entry1进行降序排序
                return entry1.getKey().compareTo(entry2.getKey());
            }
        };
        //降序  output:{dbc=9, cba=5, bca=16, abc=15}
        if (isdesc) {
            Collections.sort(sortedList, Collections.reverseOrder(comparator));
        } else {
            //升序   output:{abc=15, bca=16, cba=5, dbc=9}
            Collections.sort(sortedList, comparator);
        }
        for (Map.Entry<String, Integer> entry : sortedList) {
            String key = entry.getKey();
            Integer value = entry.getValue();
            if (StringUtils.isAnyBlank(key, String.valueOf(value))) {
                continue;
            }
            resMap.put(key, value);
        }
        return resMap;
    }

    /**
     * @describtion: 采用TreeMap的形式进行排序,默认升序
     * @author: Sundz
     * @date: 2020/1/2 22:25
     * @param: [paramMap]
     * @return: java.util.Map<java.lang.String,java.lang.Integer>
     */
    public static Map<String, Integer> ordnarySortByTreeMap(Map<String, Integer> paramMap) {
        Preconditions.checkNotNull(paramMap);
        //此处需要将非TreeMap转化成TreeMap,可采用for循环遍历的方式,然后put,但是今天我们玩点新花样
        //output:{abc=15, bca=16, cba=5, dbc=9}
        return paramMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (x, y) -> x, TreeMap::new));
    }

    /**
     * @describtion: 优雅实现排序,jdk8的新语法,最后的转化集合必须是LinkedHashMap,这样才能保持插入的顺序
     * @author: Sundz
     * @date: 2020/1/2 22:28
     * @param: [paramMap, isdesc]
     * @return: java.util.Map<java.lang.String ,java.lang.Integer>
     */
    public static Map<String, Integer> newSortByKey(Map<String, Integer> paramMap, boolean isdesc) {
        Preconditions.checkNotNull(paramMap);
        if (isdesc) { // output:{dbc=9, cba=5, bca=16, abc=15}
        //jdk8 中Map.Entry接口支持多种排序,可按键,按值、颠倒及多个比较器组合等形式进行排序
            return paramMap.entrySet().stream().sorted(Map.Entry.<String, Integer>comparingByKey().reversed()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (x, y) -> x, LinkedHashMap::new));
        } else {
            //output:{abc=15, bca=16, cba=5, dbc=9}
            return paramMap.entrySet().stream().sorted(Map.Entry.comparingByKey()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (x, y) -> x, LinkedHashMap::new));
        }
    }

2、按值排序
按照Map集合的值进行排序,也是我们经常遇到的场景,为此笔者也做了一个简单的总结,按照值进行排序可以从几个角度进行思考:

① 可采用将其转化成对应的Set集合进行排序,然后将添加至对应的Map集合,从而实现排序,如方法ordnarySortByValue所示;

② 将集合转化成Set集合,采用流的形式进行排序,最后收集成Map集合;

/**
      * @describtion: 按照值进行排序
      * @author: Sundz
      * @date: 2020/1/3 21:29
      * @param: [paramMap, isDesc]  //{bca=16, cba=5, abc=15, dbc=9}
      * @return: java.util.Map<java.lang.String,java.lang.Integer>
      */
    public static Map<String, Integer> ordnarySortByValue(Map<String, Integer> paramMap, boolean isDesc) {
        Objects.requireNonNull(paramMap);
        Comparator<Map.Entry<String, Integer>> comparator = Comparator.comparing(Map.Entry::getValue);
        Set<Map.Entry<String, Integer>> sortedSet = null;
        if (isDesc) { //output:{bca=16, abc=15, dbc=9, cba=5}
            sortedSet = FluentIterable.from(paramMap.entrySet()).toSortedSet(comparator);
        } else { //output:{cba=5, dbc=9, abc=15, bca=16}
            sortedSet = FluentIterable.from(paramMap.entrySet()).toSortedSet(Collections.reverseOrder(comparator));
        }
        Map<String, Integer> resMap = new LinkedHashMap<>(paramMap.size());
        for (Map.Entry<String, Integer> entry : sortedSet) {
            String key = entry.getKey();
            Integer value = entry.getValue();
            if (!StringUtils.isAnyBlank(key, String.valueOf(value))) {
                resMap.put(key, value);
            }
        }
        return resMap;
    }

    /**
      * @describtion: 采用Stream的形式进行排序且转化成Map集合
      * @author: Sundz
      * @date: 2020/1/3 21:37
      * @param: [paramMap, isDesc]
      * @return: java.util.Map<java.lang.String,java.lang.Integer>
      */
    public static Map<String, Integer> newSortedByValue(Map<String, Integer> paramMap, boolean isDesc) {
        Objects.requireNonNull(paramMap);
        if (isDesc) {
            return paramMap.entrySet().stream().sorted(Map.Entry.<String, Integer>comparingByValue().reversed()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (x, y) -> x, LinkedHashMap::new));
        } else {
            return paramMap.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (x, y) -> x, LinkedHashMap::new));
        }
    }

三、结束语

赠人玫瑰,手有余香,请留下您的宝贵建议或者赞吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值