How to first sort by one attribute, if equal, then sort by another attribute.

本文介绍如何在Java中实现根据两个字段进行排序的方法。首先通过Comparator实现了先按名字字母顺序排序,若名字相同则按年龄排序的例子;接着展示了如何对单词出现频率进行降序排序,当频率相同时按照单词本身的字母顺序进行升序排列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这篇文章主要demo,如何来按照两个字段进行sort。 

场景1
有一个list of  classes,每个class中的attribute 1是String name, attribute 2是  Int age。现在假设需求是先按照name 字母顺序升序排序,加入两个人同名同姓,再按照age升序排序。 在这样的场景下,就需要使用comparator去对2个字段进行排序。


场景2
有一个map,map中key是单词 String word,value是单词的词频 int count。需要对map中的单词按照count进行降序排序,如果词频一样,就按照String word单词本身进行字母顺序升序排序。


上面的场景2和场景1本质是类似的,都会用到sort。现在就来看看更麻烦一些的场景2如何写。

public class DemoOne {
    public void sortWord(String inputFileName) throws Exception{
        String line;
        HashMap<String, Integer> frequentMap = new HashMap<String, Integer> ();

        // 1 read
        // read from a file and load the file into a map.
        try (BufferedReader br = new BufferedReader(new FileReader(inputFileName))) {
            while ((line = br.readLine()) != null) {
                if (frequentMap.containsKey(line) ) {
                    frequentMap.put(line, frequentMap.get(line) + 1);
                } else {
                    frequentMap.put(line, 1);
                }
            }
        }

        // 2 sort
        // first by word count(the second attribute),
        // then by word alphabetical order(the first attribute);
        Comparator<Map.Entry<String, Integer> > comparator = 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 o1.getKey().compareTo(o2.getKey());
                } else {
                    return o2.getValue().compareTo(o1.getValue());
                }
            }
        };
        Queue<Map.Entry<String, Integer> > heap = new PriorityQueue<Map.Entry<String, Integer> >(100, comparator);
        for (Map.Entry<String, Integer> each : frequentMap.entrySet()) {
            //System.out.println( each.getValue() + ", " + each.getKey());
            heap.add(each);
        }

        //3 output after sort
        Map.Entry<String, Integer> tempEntry = null;
        while (!heap.isEmpty()) {
        //for (int i = 0; i < heap.size(); ++i) { //这是个易错的BUG,heap的size()一直再变化,所以用它作为循环条件将会悲剧。
            //System.out.println("A");
            tempEntry = heap.poll();
            System.out.println( tempEntry.getValue() + ", " + tempEntry.getKey());
        }
    }
    public static void main  (String [] args)throws Exception {
        String inputFileName = "./input.txt";
        DemoOne demoOne = new DemoOne();
        demoOne.sortWord(inputFileName);
    }
}

Sample Input 

this
cake
is
a
nice
nice
moon
cake

Sample  Output

2, cake
2, nice
1, a
1, is
1, moon
1, this


上面代码中,重点是comparator的写法。在comparator的这段代码中

            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                if (o1.getValue() == o2.getValue()) {
                    return o1.getKey().compareTo(o2.getKey());
                } else {
                    return o2.getValue().compareTo(o1.getValue());
                }
            }
先比较Map中存的<Key, Value>  pair中的value, 也就是先比较<String Word, Integer Count> 中的count, 如果不相等,那么count的比较结果就是comparator的比较结果, 也就是,

(1) 如果o1.count 较o2.count小,则返回正数(注意这里是降序排序,所以正好和升序情况相反),所以是o1.getValue()和o2.getValue()的比较。

(2) 如果o1.count较o2.count大,则返回负数(注意这里是降序排序,所以正好和升序情况相反),所以是o1.getValue()和o2.getValue()的比较。

(3) 如果二者相等,则比较o1和o2的word的字母顺序,所以所以o1.getKey()和o2.getKey()的比较。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值