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

这篇文章主要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()的比较。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值