0

0

如何使用Java 8 Stream收集Map中相同最大值的所有键

聖光之護

聖光之護

发布时间:2025-09-22 17:16:01

|

951人浏览过

|

来源于php中文网

原创

如何使用Java 8 Stream收集Map中相同最大值的所有键

本文探讨了在Java 8及更高版本中,如何从Map<String, Integer>中高效地收集所有与最大值关联的键。针对Map中可能存在多个键拥有相同最大值的情况,文章提供了两种实现策略:一种是利用Java 8 Stream API的groupingBy和max操作,另一种是采用传统循环遍历以优化性能,并附带了详细的代码示例和实现考量。

java开发中,我们经常需要处理各种数据结构。一个常见的需求是从map<string, integer>中找出具有最大值的所有键。与仅仅找出第一个最大值对应的键不同,此场景要求我们收集所有可能拥有相同最大值的键,并将它们组织成一个列表。例如,对于{"first": 50, "second": 10, "third": 50}这样的map,期望的输出是["first", "third"]。

场景示例

假设我们有以下Map数据:

final Map<String, Integer> map = new HashMap<>();
map.put("first", 50);
map.put("second", 10);
map.put("third", 50);
map.put("fourth", 20);

我们的目标是得到一个包含"first"和"third"的列表,因为它们都对应着最大值50。

方法一:使用Java 8 Stream API (groupingBy结合max)

Java 8引入的Stream API为处理集合数据提供了强大的函数式编程能力。我们可以利用Collectors.groupingBy将Map的条目按值进行分组,然后再从分组后的结果中找出最大值对应的键列表。

实现步骤

  1. 按值分组: 使用groupingBy(Map.Entry::getValue, mapping(Map.Entry::getKey, toList()))将Map.Entry流转换为Map<Integer, List<String>>。这意味着每个值(Integer)都会映射到一个包含所有对应键(List)的列表。
  2. 查找最大值组: 从上一步生成的Map<Integer, List<String>>中,通过max(Map.Entry.comparingByKey())找出键(即原始Map中的值)最大的那个条目。
  3. 提取键列表: 从找到的最大条目中提取其值,即我们想要的键列表。

示例代码

import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.stream.Collectors;

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

public class MaxKeysCollector {

    public static void main(String[] args) {
        final Map<String, Integer> map = new HashMap<>();
        map.put("first", 50);
        map.put("second", 10);
        map.put("third", 50);
        map.put("fourth", 20);

        List<String> maxKeys = map.entrySet()
                .stream()
                // 1. 按值分组:将Map.Entry流转换为 Map<Integer, List<String>>
                //    键是原始Map的值,值是所有对应这些值的键的列表。
                .collect(groupingBy(Map.Entry::getValue, mapping(Map.Entry::getKey, toList())))
                .entrySet()
                .stream()
                // 2. 查找最大值组:从分组后的Map中,找出键(即原始Map中的最大值)最大的条目。
                .max(Map.Entry.<Integer, List<String>>comparingByKey())
                // 3. 如果Map为空或没有最大值,抛出异常;否则获取其值(即键列表)。
                .orElseThrow(() -> new IllegalStateException("Map is empty or no maximum value found."))
                .getValue();

        System.out.println("使用Stream API收集的最大值键列表: " + maxKeys); // 输出: [first, third] (顺序可能不同)
    }
}

注意事项

  • 此方法使用了两次Stream操作。第一次用于分组,第二次用于查找最大值。虽然第二次Stream操作是在一个可能较小的Map上进行的,但整体上会创建中间集合。
  • orElseThrow()用于处理Map为空的情况。在实际应用中,可能需要更优雅的错误处理,例如返回一个空列表或Optional<List<String>>。
  • 输出列表的顺序可能不确定,因为HashMap和groupingBy通常不保证元素的插入顺序。

方法二:传统循环遍历(单次迭代优化性能)

对于追求极致性能或处理超大型数据集的场景,传统的循环遍历方法通常更为高效,因为它避免了中间集合的创建和多次Stream迭代的开销。

Vondy
Vondy

下一代AI应用平台,汇集了一流的工具/应用程序

下载

立即学习Java免费学习笔记(深入)”;

实现步骤

  1. 初始化: 创建一个空的List<String>来存储最大值对应的键,并初始化一个maxValue变量为Integer.MIN_VALUE来跟踪当前找到的最大值。
  2. 单次遍历: 遍历Map的每个条目。
  3. 比较与更新:
    • 如果当前条目的值小于maxValue,则跳过,因为这不是一个更大的值。
    • 如果当前条目的值大于maxValue,这意味着我们找到了一个新的最大值。此时,需要清空之前收集的maxKeys列表,因为它们对应的是旧的最大值。
    • 更新maxValue为当前条目的值。
    • 将当前条目的键添加到maxKeys列表中。

示例代码

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.HashMap;

public class MaxKeysCollectorOptimized {

    public static void main(String[] args) {
        final Map<String, Integer> map = new HashMap<>();
        map.put("first", 50);
        map.put("second", 10);
        map.put("third", 50);
        map.put("fourth", 20);

        List<String> maxKeys = new ArrayList<>();
        int maxValue = Integer.MIN_VALUE; // 初始化为Integer的最小值

        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            int currentValue = entry.getValue();
            String currentKey = entry.getKey();

            if (currentValue < maxValue) {
                // 如果当前值小于已知的最大值,则跳过
                continue;
            }

            if (currentValue > maxValue) {
                // 如果当前值大于已知的最大值,说明找到了新的最大值
                // 清空之前收集的键,因为它们对应的是旧的最大值
                maxKeys.clear();
            }

            // 更新最大值
            maxValue = currentValue;
            // 将当前键添加到列表中
            maxKeys.add(currentKey);
        }

        System.out.println("使用传统循环收集的最大值键列表: " + maxKeys); // 输出: [first, third] (顺序可能不同)
    }
}

性能考量

  • 此方法仅对Map进行一次迭代,避免了中间集合的创建,因此在大多数情况下具有更好的性能,尤其对于大型Map。
  • 代码逻辑直观,易于理解和调试。

总结

本文介绍了两种在Java 8及更高版本中从Map<String, Integer>中收集所有最大值对应键的方法:

  1. Stream API结合groupingBy: 这种方法利用函数式编程的优势,代码简洁且富有表达力,适合对可读性和声明式编程风格有较高要求的场景。但它可能涉及额外的中间集合和多次迭代,对性能有一定影响。
  2. 传统循环遍历: 这种方法通过单次迭代直接处理数据,性能表现通常更优,特别适用于处理大量数据或对性能敏感的应用。

在选择哪种方法时,应根据具体项目的需求进行权衡。对于大多数日常应用,Stream API的简洁性可能更受欢迎;而对于性能瓶颈分析后的优化,传统循环遍历则可能是更明智的选择。两种方法都能准确地解决“收集Map中相同最大值的所有键”的问题。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1051

2023.08.02

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

550

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

30

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

45

2026.01.06

golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

77

2025.09.05

golang map相关教程
golang map相关教程

本专题整合了golang map相关教程,阅读专题下面的文章了解更多详细内容。

40

2025.11.16

golang map原理
golang map原理

本专题整合了golang map相关内容,阅读专题下面的文章了解更多详细内容。

67

2025.11.17

java判断map相关教程
java判断map相关教程

本专题整合了java判断map相关教程,阅读专题下面的文章了解更多详细内容。

47

2025.11.27

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.4万人学习

C# 教程
C# 教程

共94课时 | 11.3万人学习

Java 教程
Java 教程

共578课时 | 82万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号