java8 实现map以value值排序操作

 更新时间:2020年12月08日 11:14:39   作者:Haiyoung  
这篇文章主要介绍了java8 实现map以value值排序操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

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

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值排序操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java基础之类初始化顺序示例解析

    java基础之类初始化顺序示例解析

    这篇文章主要为大家介绍了java基础之类初始化顺序示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • java WebSocket 服务端实现代码

    java WebSocket 服务端实现代码

    WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端,这篇文章主要介绍了java WebSocket 服务端代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-02-02
  • java+selenium爬取图片签名的方法

    java+selenium爬取图片签名的方法

    这篇文章主要为大家详细介绍了java+selenium爬取图片签名的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-08-08
  • idea快捷键生成getter和setter,有构造参数,无构造参数,重写toString方式

    idea快捷键生成getter和setter,有构造参数,无构造参数,重写toString方式

    这篇文章主要介绍了java之idea快捷键生成getter和setter,有构造参数,无构造参数,重写toString方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • 基于HttpServletResponse 相关常用方法的应用

    基于HttpServletResponse 相关常用方法的应用

    本篇文章小编为大家介绍,基于HttpServletResponse 相关常用方法的应用,需要的朋友参考下
    2013-04-04
  • 基于java查找并打印输出字符串中字符出现次数

    基于java查找并打印输出字符串中字符出现次数

    这篇文章主要介绍了基于java查找并打印输出字符串中字符出现次数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • Struts2学习笔记(1)-入门教程

    Struts2学习笔记(1)-入门教程

    本文是一个Struts2的简单入门教程,比较简单,希望能给大家做一个参考。
    2016-06-06
  • JAVA设计模式----建造者模式详解

    JAVA设计模式----建造者模式详解

    这篇文章主要为大家详细介绍了java实现建造者模式Builder Pattern,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • spring中bean的生命周期详解

    spring中bean的生命周期详解

    今天小编就为大家分享一篇关于spring中bean的生命周期详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • Spring Boot 中的 Native SQL基本概念及使用方法

    Spring Boot 中的 Native SQL基本概念及使用方法

    在本文中,我们介绍了 Spring Boot 中的 Native SQL,以及如何使用 JdbcTemplate 和 NamedParameterJdbcTemplate 来执行自定义的 SQL 查询或更新语句,需要的朋友跟随小编一起看看吧
    2023-07-07

最新评论