java8 实现map以value值排序操作

时间:2021-05-19

我就废话不多说了,大家还是直接看代码吧~

import java.util.Collections;import java.util.HashMap;import java.util.Map;import java.util.stream.Collector;import java.util.stream.Collectors;import java.util.LinkedHashMap; public class MapSorted{ public static void main(String[] args) { Map<String, Integer> map = new HashMap<>(); map.put("A", 3); map.put("B", 5); map.put("C", 1); map.put("D", 1); map.put("E", 9); System.out.println(map); //如果value为java对象,则需要实现Comparable接口,重写compareTo方法 Map<String, Integer> sortedMap = new LinkedHashMap<>(); Map<String, Integer> sortedMap2 = new LinkedHashMap<>(); //ASC map.entrySet().stream() .sorted(Map.Entry.<String, Integer>comparingByValue()) .forEachOrdered(x -> sortedMap.put(x.getKey(), x.getValue())); System.out.println(sortedMap); //DESC Collections.reverseOrder || reversed() map.entrySet().stream() .sorted(Collections.reverseOrder(Map.Entry.comparingByValue())) .forEachOrdered(x -> sortedMap2.put(x.getKey(), x.getValue())); // map.entrySet().stream() // .sorted(Map.Entry.<String, Integer>comparingByValue().reversed()) // .forEachOrdered(x -> sortedMap2.put(x.getKey(), x.getValue())); System.out.println(sortedMap2); //Collectors.toMap 直接返回排好序的map map = map.entrySet().stream() .sorted(Collections.reverseOrder(Map.Entry.comparingByValue())) .collect(Collectors.toMap(x -> x.getKey(), x -> x.getValue(), (x1, x2) -> x2, LinkedHashMap::new)); // map = map.entrySet().stream() // .sorted(Collections.reverseOrder(Map.Entry.comparingByValue())) // .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (x1, x2) -> x2, LinkedHashMap::new)); System.out.println(map); }}{A=3, B=5, C=1, D=1, E=9}{C=1, D=1, A=3, B=5, E=9}{E=9, B=5, A=3, C=1, D=1}{E=9, B=5, A=3, C=1, D=1}

补充知识:Java8-2-Lambda表达式实战-一句话实现Map中按照Value排序

今天我们来实战一把, 对Map的Value值排序进行简化.

在以前的思路我们的做法如下:

  /** * * Map根据value排序; * * @param map * @return */ public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) { List<Map.Entry<K, V>> list = new LinkedList<>(map.entrySet()); Collections.sort(list, new Comparator<Map.Entry<K, V>>() { @Override public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) { return (o2.getValue()).compareTo(o1.getValue()); } }); Map<K, V> result = new LinkedHashMap<>(); for (Map.Entry<K, V> entry : list) { result.put(entry.getKey(), entry.getValue()); } return result; }

什么意思呢?意思就是先把Map变成可排序的List使用Comparator接口对entry进行排序, 可是这样代码很多很乱, 我们需要做一些简化.

第一步: 使用Lambda表达式先对Comparator接口做简化, 代码会变成如下情况:

public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) { List<Map.Entry<K, V>> list = new LinkedList<>(map.entrySet()); list.sort(Comparator.comparing(Entry::getValue)); Map<K, V> result = new LinkedHashMap<>(); for (Map.Entry<K, V> entry : list) { result.put(entry.getKey(), entry.getValue()); } return result; }

这样的话, 一行代码就代替了五行, 但是会有个问题, 这样写只能从小到大排序很不灵活, 我们还有其他办法.来看下面的代码:

public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) { List<Map.Entry<K, V>> list = new LinkedList<>(map.entrySet()); list.sort((o1, o2)-> o2.getValue().compareTo(o1.getValue())); Map<K, V> result = new LinkedHashMap<>(); for (Map.Entry<K, V> entry : list) { result.put(entry.getKey(), entry.getValue()); } return result; }

用lambda表达式就可以做到变换排序的方式, 只要改变o1和o2的顺序就可以了.哎, 可以还是很长, 我还想再少几句代码, 怎么办?

我们来分析下最原始的排序代码 ---> 首先是将Map转化为List<Entry>利用List的可排序的特性排序后遍历到新的Map里面去, 这样就很简单了, 我们可以从遍历的地方入手.代码如下:

public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) { List<Map.Entry<K, V>> list = new LinkedList<>(map.entrySet()); list.sort((o1, o2)-> o2.getValue().compareTo(o1.getValue())); Map<K, V> result = new LinkedHashMap<>(); list.stream().forEach(entry -> result.put(entry.getKey(), entry.getValue())); return result; }

也许做到上面这一步已经很满足了, 可是作为一个优秀的开发人员怎么能满足于这种程度, 我们要用两句话完成上面的功能.我们可以发现entrySet()是个集合, stream是有sort方法的, 可以set变成stream然后sort之后forEach到新的Map中, 牛逼吧, 废话少说,看代码.

public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) { Map<K, V> sortMap = new LinkedHashMap<>(); new map.entrySet().stream() .sorted((o1, o2) -> o2.getValue().compareTo(o1.getValue())) .forEach(entry -> sortMap.put(entry.getKey(), entry.getValue())); return sortMap; }

高级程序员到这里就可以了, 下面提供一个工具类给大家使用.

/** * flag = 1 正序 * flag = 0 倒序 * @param map * @param flag * @return */ public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map, int flag) { Map<K, V> sortMap = new LinkedHashMap<>(); if(flag == 1) { map.entrySet().stream() .sorted((o1, o2) -> o1.getValue().compareTo(o2.getValue())) .forEach(entry -> sortMap.put(entry.getKey(), entry.getValue())); } else { map.entrySet().stream() .sorted((o1, o2) -> o2.getValue().compareTo(o1.getValue())) .forEach(entry -> sortMap.put(entry.getKey(), entry.getValue())); } return sortMap; }

以上的代码已经够简洁了, 但是有一个中间变量, 我作为一个究极程序员是看不惯的, 能不能把它也省略掉一句代码实现整个功能呢? 答案是可以的.

public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue2(Map<K, V> map, int flag) { if(flag == 1) { return map.entrySet().stream().sorted((o1, o2) -> o1.getValue().compareTo(o2.getValue())).map(entry -> { Map<K, V> result = new LinkedHashMap<>(); result.put(entry.getKey(), entry.getValue()); return result; }).reduce((map1, map2) -> { map2.entrySet().forEach(entry -> map1.put(entry.getKey(), entry.getValue())); return map1; }).get(); } else { return map.entrySet().stream().sorted((o1, o2) -> o2.getValue().compareTo(o1.getValue())).map(entry -> { Map<K, V> result = new LinkedHashMap<>(); result.put(entry.getKey(), entry.getValue()); return result; }).reduce((map1, map2) -> { map2.entrySet().forEach(entry -> map1.put(entry.getKey(), entry.getValue())); return map1; }).get(); }

思路是做好排序后将排序后的entry加入到新的Map里面, 再将stream<Map<K,V>>进行叠加, 可能有些抽象, 不能明白的也只能帮到这啦.

以上这篇java8 实现map以value值排序操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章