给Map定制排序规则

一、从TreeMap说起

TreeMap中自带了一个比较器comparator,所以它有默认的排序方法

我们先来看个小例子:

public static void main(String[] args) {
        Map<String, Integer> map = new TreeMap<>();
        map.put("ZhangSan", 35);
        map.put("LiSi", 25);
        map.put("WangWu", 35);
        map.put("XiaoHong", 15);
        map.put("YaSe", 27);
        for (String s : map.keySet()) {
            System.out.println("姓名:"+s+", 年龄:"+map.get(s));
        }
    }

从下图中可以看到运行的结果是按照Key值升序来排的:

因为TreeMap提供了将比较器作为传参的方式传入TreeMap中的构造方法,所以我们在创建TreeMap的时候也可以通过传参来定制TreeMap的排序规则。

//下面这个是TreeMap中传入比较器的构造方法
public TreeMap(Comparator<? super K> comparator) {
        this.comparator = comparator;
    }

我们继续使用上面的那个例子并修改代码,在创建TreeMap的时候传入一个比较器,使得其中的map中的元素按照健值降序排序并输出:

public static void main(String[] args) {
        Map<String, Integer> map = new TreeMap<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o2.compareTo(o1);
            }
        });
        map.put("ZhangSan", 35);
        map.put("LiSi", 25);
        map.put("WangWu", 35);
        map.put("XiaoHong", 15);
        map.put("YaSe", 27);
        for (String s : map.keySet()) {
            System.out.println("姓名:"+s+", 年龄:"+map.get(s));
        }
    }

 得到如下结果:

 二、按照value的值来进行排序

细心的小伙伴们可能会发现,我们刚才都是使用key值来排序的,如果想要使用value来进行排序,又应该怎么设置呢?

这个时候我们要使用到Map类中的一个内部接口Entry<k,v>,可以通过将map中的键值对转换为Entry类型,然后放入到Collection类型的容器中,再通过在Collections.sort()方法中自定义比较器来定制排序。首先我们使用这个方法来实现以下上述的例子(为了和TreeMap中自带的比较器区分,我们使用HashMap来实现)

public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("ZhangSan", 35);
        map.put("LiSi", 25);
        map.put("WangWu", 35);
        map.put("XiaoHong", 15);
        map.put("YaSe", 27);
        System.out.println("排序前:");
        for (String s : map.keySet()) {
            System.out.println("姓名:"+s+", 年龄:"+map.get(s));
        }
        //此处其实通过了中介List来实现排序的
        List<Map.Entry<String, Integer>> list = new LinkedList<>(map.entrySet());
        Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
            @Override
            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                return o1.getKey().compareTo(o2.getKey());
            }
        });
        System.out.println("排序后:");
        for (Map.Entry<String, Integer> entry : list) {
            System.out.println("姓名:"+entry.getKey()+", 年龄:"+entry.getValue());
        }
    }

输出结果如下:

 

当然,你也可以通过修改 比较器的逻辑来修改排序方式。

使用Entry的方式来进行排序的话,不仅仅可以通过键值来排序,也可以通过值来排序:

public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("ZhangSan", 35);
        map.put("LiSi", 25);
        map.put("WangWu", 35);
        map.put("XiaoHong", 15);
        map.put("YaSe", 27);
        System.out.println("排序前:");
        for (String s : map.keySet()) {
            System.out.println("姓名:"+s+", 年龄:"+map.get(s));
        }
        //此处其实通过了中介List来实现排序的
        List<Map.Entry<String, Integer>> list = new LinkedList<>(map.entrySet());
        Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
            @Override
            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                //年龄相同时,按照姓名降序排序
                if (o1.getValue() == o2.getValue()) {
                    return o2.getKey().compareTo(o1.getKey());
                }
                //按照年龄升序排序
                return o1.getValue() - o2.getValue();
            }
        });
        System.out.println("排序后:");
        for (Map.Entry<String, Integer> entry : list) {
            System.out.println("姓名:"+entry.getKey()+", 年龄:"+entry.getValue());
        }

    }

上面的例子不仅定制了按照年龄升序来排序,同时在年龄相等的情况下,会按照姓名降序的方式来排序。具体的运行结果如下:

三、做个小补充

在【二】中,我们使用了Entry的方式来给Map定制排序,其中使用的是HashMap。需要注意的是,HashMap中并没有定义比较器,所以它是不能够自动安装key来排序的。那么如果在不使用Entry的前提下,有没有什么方法可以给HashMap安装key排序呢?

答案是有的,可以通过下面的例子来看看:

public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("ZhangSan", 35);
        map.put("LiSi", 25);
        map.put("WangWu", 35);
        map.put("XiaoHong", 15);
        map.put("YaSe", 27);
        System.out.println("排序前:");
        for (String s : map.keySet()) {
            System.out.println("姓名:"+s+", 年龄:"+map.get(s));
        }
        System.out.println("排序后:");
        List<String> listKey = new LinkedList<>(map.keySet());
        //此处如果不传入自己定制的比价器,即Collections.sort(listKey);
        //那么结果输出结果是按照key升序排序的
        Collections.sort(listKey, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o2.compareTo(o1);
            }
        });
        for (String s : listKey) {
            System.out.println("姓名:"+s+", 年龄:"+map.get(s));
        }
    }

 运行结果如下:

其实,究其本质,该例子和【二】中一样都是借用了Collection来进行排序,在平时的刷题中,如果可以灵活的去定制一个比较器,有时候会让你事半功倍,少写很多代码。

 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值