Map集合排序——根據value對key進行排序
在流水的業務中,碼出最優雅的代碼。
描述:有若干個鍵值對格式的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<String, Integer>
的排序開始,其他類型可自行替換
在JDK8 以前,一般都是這樣寫:
public static void main(String[] args) {
//這裏自定義一個需要排序的map集合
Map<String, Integer> map = new HashMap<String, Integer>();
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<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)
return o1.getValue().compareTo(o2.getValue());
};
});
for (Entry<String, Integer> 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<String, Integer> map = new HashMap<String, Integer>();
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<String> 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<String, Integer> map = new HashMap<String, Integer>();
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<String> keys = sortMapByValue(map);
for (String key : keys){
System.out.println(key);
}
}
好像這樣看起來簡潔多了,而且還多了一個可複用的東西,但是,這樣在JDK1.8中還遠遠不夠。
在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<String, Integer> map = new HashMap<String, Integer>();
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<String> 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<String, Integer>::getValue)
:顧名思義,就是此處的比較規則,Map.Entry
中有getKey()
,getValue()
等方法,通過改變取值,就可以改變排序對象,而默認排序爲自然排序,reversed()
:該方法將 其改變爲倒序;
4、map(Map.Entry<String, Integer>::getKey)
:此處將Entry<String, Integer>
中的key
單獨抽離出來;
5、collect(Collectors.toList())
:告訴程序返回的是一個List集合;
全文到此,對JDK1.8中的新特性還不熟悉的仔仔們,可以去看一些相關文檔,預計下一篇爲:《List集合排序——彙總》