在流水的业务中,码出最优雅的代码。
描述:有若干个键值对格式的json字符串,根据其中的value进排序,取出其中的排位靠前的一半以上的key值,json数据为:{“1.B.1.f”:”1.8”,”1.B.1.e”:”2.5”,”1.B.1.b”:”3.0”,”1.B.1.d”:”3.0”,”1.B.1.a”:”3.5”,”1.B.1.c”:”2.3”},这是业务上的一个需求,于是针对这个需求就有了对Map的排序一系列探索
前言:对于json转Map本篇就不介绍,直接从对
Map
的排序开始,其他类型可自行替换
public static void main(String[] args) {
//这里自定义一个需要排序的map集合
Map map = new HashMap();
map.put("1.B.1.c", 45);
map.put("1.B.1.d", 65);
map.put("1.B.1.a", 12);
map.put("1.B.1.b", 15);
map.put("1.B.1.e", 78);
int size = map.size();
// 通过map.entrySet()将map转换为"1.B.1.e=78"形式的list集合
List> list = new ArrayList>(size);
list.addAll(map.entrySet());
// 通过Collections.sort()排序
Collections.sort(list, new Comparator>() {
public int compare(Map.Entry o1, Map.Entry o2) {
// compareTo方法 (x < y) ? -1 : ((x == y) ? 0 : 1)
return o1.getValue().compareTo(o2.getValue());
};
});
for (Entry entry : list){
// 得到排序后的键值
System.out.println(entry.getKey());
}
}
有时候我们会想,把这个方法提炼出来,放在一个工具类中,如是我们将会这样做:
public static List<String> sortMapByValue(Map<String, Integer> map){
int size = map.size();
//通过map.entrySet()将map转换为"1.B.1.e=78"形式的list集合
List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(size);
list.addAll(map.entrySet());
//通过Collections.sort()排序
Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
// compareTo方法 (x < y) ? -1 : ((x == y) ? 0 : 1)
// 倒序:o2.getValue().compareTo(o1.getValue())
// 顺序:o1.getValue().compareTo(o2.getValue())
return o2.getValue().compareTo(o1.getValue());
};
});
List<String> keys = new ArrayList<String>(size);
for (Entry<String, Integer> entry : list){
// 得到排序后的键值
keys.add(entry.getKey());
}
return keys;
}
public static void main(String[] args) {
//这里自定义一个需要排序的map集合
Map map = new HashMap();
map.put("1.B.1.a", 45);
map.put("1.B.1.e", 65);
map.put("1.B.1.c", 12);
map.put("1.B.1.b", 15);
map.put("1.B.1.d", 78);
List keys = sortMapByValue(map);
for (String key : keys){
System.out.println(key);
}
}
看起来好像有点复杂,而且实现Comparator接口的比较器好像可以抽离出来,其他地方也可以复用,于是:
public static List<String> sortMapByValue(Map<String, Integer> map) {
int size = map.size();
//通过map.entrySet()将map转换为"1.B.1.e=78"形式的list集合
List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(size);
list.addAll(map.entrySet());
//通过Collections.sort()排序
Collections.sort(list, new ValueComparator());
List<String> keys = new ArrayList<String>(size);
for (Entry<String, Integer> entry : list){
// 得到排序后的键值
keys.add(entry.getKey());
}
return keys;
}
private static class ValueComparator implements Comparator<Map.Entry<String, Integer>> {
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
// compareTo方法 (x < y) ? -1 : ((x == y) ? 0 : 1)
// 倒序:o2.getValue().compareTo(o1.getValue()),顺序:o1.getValue().compareTo(o2.getValue())
return o2.getValue().compareTo(o1.getValue());
}
}
public static void main(String[] args) {
//这里自定义一个需要排序的map集合
Map map = new HashMap();
map.put("1.B.1.a", 45);
map.put("1.B.1.e", 65);
map.put("1.B.1.c", 12);
map.put("1.B.1.b", 15);
map.put("1.B.1.d", 78);
List keys = sortMapByValue(map);
for (String key : keys){
System.out.println(key);
}
}
好像这样看起来简洁多了,而且还多了一个可复用的东西,但是,这样在JDK1.8中还远远不够。
public static List<String> sortMapByValue(Map<String, Integer> map) {
int size = map.size();
//通过map.entrySet()将map转换为"1.B.1.e=78"形式的list集合
List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(size);
list.addAll(map.entrySet());
List<String> keys = list.stream()
.sorted(Comparator.comparing(Map.Entry<String, Integer>::getValue).reversed())
.map(Map.Entry<String, Integer>::getKey)
.collect(Collectors.toList());
return keys;
}
public static void main(String[] args) {
//这里自定义一个需要排序的map集合
Map map = new HashMap();
map.put("1.B.1.a", 45);
map.put("1.B.1.e", 65);
map.put("1.B.1.c", 12);
map.put("1.B.1.b", 15);
map.put("1.B.1.d", 78);
List keys = sortMapByValue(map);
keys.forEach(System.out::println);
}
惊不惊喜,意不意外。
在JDK 1.8中新增了函数式编程,对上述代码的解释为:
1、先将list集合转换为流,即:list.stream()
,值得注意的是:在stream()中所做的任何操作都不会影响到原集合;
2、sorted()
方法:对list集合进行排序,具体见下一篇专门针对List排序的介绍;
3、Comparator.comparing(Map.Entry
:顾名思义,就是此处的比较规则,::getValue) Map.Entry
中有getKey()
,getValue()
等方法,通过改变取值,就可以改变排序对象,而默认排序为自然排序,reversed()
:该方法将 其改变为倒序;
4、map(Map.Entry
:此处将::getKey) Entry
中的key
单独抽离出来;
5、collect(Collectors.toList())
:告诉程序返回的是一个List集合;
全文到此,对JDK1.8中的新特性还不熟悉的仔仔们,可以去看一些相关文档,预计下一篇为:《List集合排序——汇总》