How to first sort by one attribute, if equal, then sort by another attribute.
2015-09-28 13:12
405 查看
这篇文章主要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如何写。
Sample Input
Sample Output
上面代码中,重点是comparator的写法。在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()的比较。
场景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()的比较。
相关文章推荐
- Android 个人开发者接入支付功能
- EasyARM-iMX257 linxu两年前的笔记
- shareSDK社会化分享快速集成
- 拼图游戏图片的分割与移动
- 第4周实践项目5--猴子选大王
- C语言变量的存储方式和生存期
- JS跳转页面的几种方式
- SQL SERVER的事务SQL语句
- docker 源码分析 二(基于1.8.2版本),docker client与daemon交互
- ListView与ScrollView的联动
- EasyARM-iMX257 linux两年前的笔记
- iOS页面间传值的方式(Delegate/NSNotification/Block/NSUserDefault/单例)
- Intellij IDEA如何使用Maven Tomcat Plugin运行web项目
- Xcode7 制作通用的framework
- LinearLayout学习笔记
- mysql 操作 指南
- OpenCV3.0基本类型初探(三)MAT初探
- 程序员生涯回顾,并响应“自由飞”的《架构之路》
- 运行Python脚本的一种方法
- phpStudy for Linux (lnmp+lamp一键安装包)