java中经常排序,但是自己对Map的排序方法一直不是很清楚,特此记录。
Map作为键值对的存储工具,基本的概念介绍网上都有,自己参考如下博客:
https://www.cnblogs.com/chenssy/p/3264214.html
简单介绍Map
在讲解Map排序之前,我们先来稍微了解下map。map是键值对的集合接口,它的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等。其中这四者的区别如下(简单介绍)一般使用HashMap和TreeMap
本文正文下面式排序方式的介绍:
Map的排序方式一 直接使用TreeMap进行排序
public class test {
public static void main(String[] args) {
Map<String, String> map = new TreeMap<>();
map.put("a", "I'am a");
map.put("c", "I'am c");
map.put("d", "I'am d");
map.put("b", "I'am b");
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue());
}
}
}
输出的结果如下:
a I’am a
b I’am b
c I’am c
d I’am d
但是上面的排序默认是按照Key值进行排序的,并且按照的是默认的升序排序,如果我们想改变默认的排序方式,即按照我们自己的比较方式排序,我们就需要实现自己的比较器,实现方式如下(下面的这种实现方式只能根据key值进行排序):
下面的代码实现了根据key值进行降序排序
public class test {
public static void main(String[] args) {
Map<Integer, String> map = new TreeMap<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
// 上面的Map可也以写成lambda表达式的形式 Map map = //new TreeMap<>((o1, o2) -> o2 - o1);
map.put(3, "I'am 3");
map.put(0, "I'am 0");
map.put(2, "I'am 2");
map.put(1, "I'am 1");
for (Map.Entry<Integer, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue());
}
}
}
输出:
3 I’am 3
2 I’am 2
1 I’am 1
0 I’am 0
以上的排序方法都是根据Key值进行排序,如果我们想根据value进行排序或者根据value和key进行排序,我们可以使用如下的方法
首先将map中的值转存到list中,然后对List进行排序,之后将list排序结果取出,再存储到LinkedHashMap中
public class test {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("I am d", "aaad");
map.put("I am c", "cs");
map.put("I am b", "baa");
map.put("I am a", "a");
List<Map.Entry<String, String>> list = new LinkedList<>(map.entrySet());
// 下面的也可以写成lambda表达式这种形式
// Collections.sort(list, (o1, o2) -> o2.getValue().compareTo(o1.getValue()));
Collections.sort(list, new Comparator<Map.Entry<String, String>>() {
@Override
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
return o2.getValue().compareTo(o1.getValue()); // 这里改为根据value值进降序排序,这里也可以改成根据key和value进行排序
}
});
Map<String, String> result = new LinkedHashMap<>();
for (Map.Entry<String, String> entry : list) {
result.put(entry.getKey(), entry.getValue());
}
System.out.println(result);
}
}
输出结果:
{I am c=cs, I am b=baa, I am d=aaad, I am a=a}
这种自己平常不太使用,自己通常使用stream进行排序。
Map排序方法二:使用stream进行排序
Map<Integer, String> map = new HashMap<>();
map.put(100, "I'am a");
map.put(99, "I'am c");
map.put(2, "I'am d");
map.put(33, "I'am b");
// 按照value进行倒排,如果要根据key进行排序的话使用Map.Entry.comparingByKey()
map.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
.forEach(System.out::println);
// 根据value进行正序排序,根据key进行排序的话使用comparingByKey()
map.entrySet().stream().sorted(Map.Entry.comparingByValue()).forEach(System.out::println);
// 如果要将排序的结果返回的话,我们可以使用下面的方法(注意:要使用LinkedHashMap进行保存,linkedHashMap可以保存插入顺序)
Map<Integer, String> resultMap1 = map.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (s, s2) -> s,
LinkedHashMap::new));
// 下面的这种写法同上面的写法,只不过是将简写展开了,这样更易于理解
Map<Integer, String> resultMap = map.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(new Function<Map.Entry<Integer, String>, Integer>() {
@Override
public Integer apply(Map.Entry<Integer, String> integerStringEntry) {
return integerStringEntry.getKey();
}
}, new Function<Map.Entry<Integer, String>, String>() {
@Override
public String apply(Map.Entry<Integer, String> integerStringEntry) {
return integerStringEntry.getValue();
}
}, new BinaryOperator<String>() {
@Override
public String apply(String s, String s2) {
return s;
}
}, new Supplier<Map<Integer, String>>() {
@Override
public Map<Integer, String> get() {
return new LinkedHashMap<>();
}
}));
// 同样如果需要将排序的将结果作为Map进行返回我们还可以使用下面的方法,但是不推荐这种方式(effectivejava 178页中说:foreach操作应该只用于报告stream计算的结果,而不是执行计算)
Map<Integer, String> result2 = new LinkedHashMap<>();
map.entrySet().stream().sorted(Map.Entry.comparingByValue()).forEach(new Consumer<Map.Entry<Integer, String>>() {
@Override
public void accept(Map.Entry<Integer, String> integerStringEntry) {
result2.put(integerStringEntry.getKey(), integerStringEntry.getValue());
}
});
https://www.jianshu.com/p/d20d2afbf87e
https://www.cnblogs.com/zimug/p/11781375.html
https://blog.csdn.net/hao134838/article/details/80780622