Java 8 – 按值升序和降序对 HashMap 进行排序

位置:首页>文章>详情   分类: Java教程 > 编程技术   阅读(494)   2024-01-28 07:14:57

在上一篇文章中,我向您展示了如何在 Java 8 中通过键对 Map 进行排序,今天,我将教您使用 Java 如何通过值对 Map 进行排序 8 个特征,例如lambda 表达式、方法引用、流和添加到 java.util.Comparator 和 Map.Entry 类中的新方法。为了对任何Map进行排序,例如HashMap、Hashtable、LinkedHashMap、TreemMap,甚至ConcurrentHashMap,您可以先使用 entrySet() 方法获取条目集,然后可以通过调用流()方法。 entrySet() 方法返回一个 Set,它继承了 java.util.Collection 类的 stream() 方法。获得流后,您只需调用 sorted() 方法即可使用 Comparator 对 Stream 中可用的所有 Map.Entry 对象进行排序。

为了按值比较 Map 的条目,您可以使用 java.util.Map.Entry 类中新添加的 Map.Entry.comparingByValue() 方法。

这是我们在上一篇文章中使用的 comparingByKey() 方法的对应方法。这两种方法都被重载以与 Comparable 和 Comparator 对象一起使用。

一旦你对流进行排序,你就可以做任何你想做的事情,例如如果您只想按排序顺序打印键、值或条目,只需使用 forEach() 方法,或者如果您想要一个按值排序的 Map,则可以使用 collect() 方法流类。

此方法接受 Collector 并允许您将 Stream 的所有元素捕获到您想要的任何集合中。例如,如果您想要一个排序的Map,那么您可以使用 java.util.stream.Collectors 类的 toMap() 方法。

这个方法被重载并提供了几个选择,例如,你可以在任何类型的Map中收集条目,或者你也可以指定你想要的Map类型,例如为了保持条目排序,我们将使用 LinkedHashMap。它还允许您在相同值的情况下打破联系,例如你可以按照你想要的顺序排列它们。

顺便说一句,如果你很好奇,你也可以看看 Pluralsight 的 From Collections to Streams in Java 8 Using Lambda Expressions 课程来了解更多关于 Java 8 的新特性,这是特定于集合框架的。

简而言之,这里是在 Java 8 中按值对 HashMap 进行排序的确切步骤,假设您已经有一个 map 对象

  1. 调用Map.entrySet()方法获取条目集
  2. 调用stream()方法获取条目流
  3. 使用比较器调用排序方法
  4. 使用 Map.Entry.comparingByValue() 比较器按值对条目进行排序
  5. 使用 collect() 方法收集结果
  6. 使用 Collectors.toMap() 方法在另一个 Map 中获取结果。
  7. 为最后一个参数提供 LinkedHashMap::new 以强制它返回一个 LinkedHashMap,以保持排序顺序不变
  8. 为了按降序排序,只需使用 Java 8 的 Collections.reverseOrder() 或 Comparator.reverse() 方法反转 Comparator 的顺序。参见 Java SE 8 for Really Impatient添加到关键 Java 类中的新方法的完整列表,例如Java Collection Framework、String、Comparator等

执行此步骤后,您将获得一个按值排序的Map。现在您已经了解了理论和步骤,让我们看看下一节中的代码示例以正确理解它。

Java 程序按值对 Map 进行排序

这是我们完整的 Java 程序,使用 Java 8 功能按值对 Map 进行排序,例如通过使用接口上的默认方法和静态方法对 Java 8 中的现有类进行新方法的改进。在这个例子中,我有一个项目Map及其费用的Map,例如租金,公用事业,交通等。Map key是String,代表item,value是Integer,代表费用。我们的任务是按值对 Map 进行排序,找出哪个项目花费最多,并按值的降序打印所有项目。

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import static java.util.stream.Collectors.*;
import static java.util.Map.Entry.*;

/*
 * Java Program to sort a Map by values in Java 8
 * 
 */
public class Main {

  public static void main(String[] args) throws Exception {

    // a Map with string keys and integer values
    Map<String, Integer> budget = new HashMap<>();
    budget.put("clothes", 120);
    budget.put("grocery", 150);
    budget.put("transportation", 100);
    budget.put("utility", 130);
    budget.put("rent", 1150);
    budget.put("miscellneous", 90);

    System.out.println("map before sorting: " + budget);

    // let's sort this map by values first
    Map<String, Integer> sorted = budget
        .entrySet()
        .stream()
        .sorted(comparingByValue())
        .collect(
            toMap(e -> e.getKey(), e -> e.getValue(), (e1, e2) -> e2,
                LinkedHashMap::new));

    System.out.println("map after sorting by values: " + sorted);

    // above code can be cleaned a bit by using method reference
    sorted = budget
        .entrySet()
        .stream()
        .sorted(comparingByValue())
        .collect(
            toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2,
                LinkedHashMap::new));

    // now let's sort the map in decreasing order of value
    sorted = budget
        .entrySet()
        .stream()
        .sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
        .collect(
            toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2,
                LinkedHashMap::new));

    System.out.println("map after sorting by values in descending order: "
        + sorted);
  }

}

Output
map before sorting: {grocery=150, utility=130, miscellneous=90, rent=1150,
 clothes=120, transportation=100}
map after sorting by values: {miscellneous=90, transportation=100,
 clothes=120, utility=130, grocery=150, rent=1150}
map after sorting by values in descending order: {rent=1150, grocery=150,
 utility=130, clothes=120, transportation=100, miscellneous=90}

您可以看到,在对Map进行排序之前,Map在值方面具有随机顺序,但首先,我们按值的升序对它们进行排序,然后我们按值的降序对同一Map进行排序,这就是租金排在第一位的原因,因为它让我们付出了最高的代价。

一些技巧

1)使用static import来缩短代码,你可以静态导入Map.Entry和Collectors类。

2) 尽可能使用方法引用代替 lambda 表达式。如果您不熟悉,请参阅这篇文章,了解有关如何在 Java 8 中将 lambda 表达式转换为方法引用的更多信息。

这就是关于如何在 Java 8 中按值对 Map 进行排序。您可以看到使用添加到现有类的新方法对 Map 进行排序非常容易。由于 JDK 8 的默认方法特性,所有这些都是可能的,它允许您向现有类添加新方法。在此增强之前,在 Java 中不可能不破坏现有的接口客户端,因为一旦向接口添加新方法,它的所有客户端都必须实现它。如果方法是默认的或静态的,则不再需要这样做,因为它们不是抽象的而是具体的方法。

进一步阅读

Java 8 的新特性

真正不耐烦的 Java SE 8

在 Java 8 中使用 Lambda 表达式从集合到流

相关 Java 8 教程

如果你有兴趣了解更多关于 Java 8 的新特性,这里是我之前的文章,涵盖了 Java 8 的一些重要概念:

  • 从零开始学习 Java 8 的 5 本书(书籍
  • Java 8 中的默认方法是什么? (例子
  • 如何在 Java 8 中连接字符串(示例
  • 如何在 Java 8 中使用 filter() 方法(教程
  • 如何在 Java 8 中使用 LocalDateTime 格式化/解析日期? (教程
  • 如何在 Java 8 中使用 Stream 类(教程
  • 如何在 Java 8 中将 List 转换为 Map(解决方案
  • Java 8 中抽象类和接口的区别? (回答
  • Java 8 中日期和时间的 20 个示例(教程
  • 如何在 Java 8 中使用 peek() 方法(示例
  • 如何在 Java 8 中按键对Map进行排序? (例子
  • 如何在 Java 8 中根据值对 may 进行排序? (例子
  • Java 8 中可选的 10 个例子? (例子

感谢您到目前为止阅读本文。如果您喜欢这篇文章,请与您的朋友和同事分享。如果您有任何问题或建议,请发表评论。

标签2: Java教程
地址:https://www.cundage.com/article/jcg-java-8-sorting-hashmap-values-ascending-descending-order.html

相关阅读

Java HashSet 教程展示了如何使用 Java HashSet 集合。 Java哈希集 HashSet 是一个不包含重复元素的集合。此类为基本操作(添加、删除、包含和大小)提供恒定时间性...
SpringApplicationBuilder 教程展示了如何使用 SpringApplicationBuilder 创建一个简单的 Spring Boot 应用程序。 春天 是用于创建企业应...
通道是继 buffers 之后 java.nio 的第二个主要新增内容,我们在之前的教程中已经详细了解了这一点。通道提供与 I/O 服务的直接连接。 通道是一种在字节缓冲区和通道另一端的实体(通...
课程大纲 Elasticsearch 是一个基于 Lucene 的搜索引擎。它提供了一个分布式的、支持多租户的全文搜索引擎,带有 HTTP Web 界面和无模式的 JSON 文档。 Elasti...
解析器是强大的工具,使用 ANTLR 可以编写可用于多种不同语言的各种解析器。 在这个完整的教程中,我们将: 解释基础:什么是解析器,它可以用来做什么 查看如何设置 ANTLR 以便在 Java...
Java 是用于开发各种桌面应用程序、Web 应用程序和移动应用程序的最流行的编程语言之一。以下文章将帮助您快速熟悉 Java 语言,并迈向 API 和云开发等更复杂的概念。 1. Java语言...
Java中的继承是指子类继承或获取父类的所有非私有属性和行为的能力。继承是面向对象编程的四大支柱之一,用于提高层次结构中类之间的代码可重用性。 在本教程中,我们将了解 Java 支持的继承类型,...
Java Message Service 是一种支持正式通信的 API,称为 网络上计算机之间的消息传递。 JMS 为支持 Java 程序的标准消息协议和消息服务提供了一个通用接口。 JMS 提...
Java 项目中的一项常见任务是将日期格式化或解析为字符串,反之亦然。解析日期意味着你有一个代表日期的字符串,例如“2017-08-3”,你想把它转换成一个代表 Java 中日期的对象,例如Ja...
之前,我介绍了spring 3 + hibernate 集成 示例和struts 2 hello world 示例。在本教程中,我将讨论在将 spring 框架与 struts 与 hibern...