0

0

Java 8:从 Map 中提取所有最大值对应的键列表

碧海醫心

碧海醫心

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

|

671人浏览过

|

来源于php中文网

原创

java 8:从 map 中提取所有最大值对应的键列表

本教程将深入探讨如何在 Java 8 及更高版本中,从 Map 集合中高效地获取所有与最大数值关联的键列表。我们将介绍两种主要方法:利用 Stream API 的 groupingBy 和 max 操作实现简洁的解决方案,以及采用传统单次迭代循环以优化性能。

理解问题:收集所有最大值键

在处理 Map 类型的数据时,一个常见的需求是找到具有最大值的键。然而,当多个键可能共享相同的最大值时,例如在一个映射 {"first": 50, "second": 10, "third": 50} 中,我们期望的输出是 [first, third],而不是仅仅 first 或 third 中的一个。

传统的 Stream API max(Map.Entry.comparingByValue()) 操作通常只会返回一个 Optional,即使存在多个具有相同最大值的 Entry,它也只会选择其中一个。因此,我们需要更精细的方法来收集所有符合条件的键。

方法一:利用 Java 8 Stream API 进行分组与聚合

Java 8 的 Stream API 提供了强大且富有表达力的方式来处理集合数据。通过结合 Collectors.groupingBy 和 Collectors.mapping,我们可以优雅地解决此问题。

核心思想

这种方法的核心在于将原始的 Map 首先转换为一个 Map>,其中键是原始的数值,值是所有拥有该数值的键的列表。转换完成后,我们只需找到这个新 Map 中最大的键(即原始数据的最大值),并取出其对应的键列表即可。

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

实现步骤

  1. 创建 Entry Stream:从原始 Map 中获取 entrySet() 并转换为 Stream>。
  2. 按值分组:使用 Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList())) 将 Entry 流按其值(Integer)进行分组。groupingBy 的第一个参数 Map.Entry::getValue 指定了分组的依据,第二个参数 mapping(Map.Entry::getKey, toList()) 是一个下游收集器,它将每个分组中的 Map.Entry 的键(String)提取出来并收集到一个 List 中。这一步的结果是一个 Map>。
  3. 查找最大值分组:对新生成的 Map> 的 entrySet() 再次创建 Stream。
  4. 获取最大键对应的列表:使用 max(Map.Entry.>comparingByKey()) 找到这个 Stream 中键(即原始值)最大的 Entry。最后,通过 orElseThrow().getValue() 获取到这个最大键对应的 List

示例代码

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

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toList;

public class MaxKeysCollector {

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

        List maxKeysStream = map.entrySet()
                .stream()
                // 1. 按值分组,将Map转换为Map>
                .collect(groupingBy(Map.Entry::getValue, mapping(Map.Entry::getKey, toList())))
                .entrySet()
                .stream()
                // 2. 找到新Map中键(即原始值)最大的Entry
                .max(Map.Entry.>comparingByKey())
                // 3. 取出最大值对应的键列表
                .orElseThrow(() -> new IllegalStateException("Map cannot be empty to find max keys."))
                .getValue();

        System.out.println("Stream API 结果: " + maxKeysStream); // 预期输出: [first, third, fifth] (顺序可能不同)
    }
}

注意事项

这种方法简洁且具有声明式风格,代码可读性强。然而,它涉及两次 Stream 迭代和一次中间 Map 的创建。对于包含大量数据的 Map,这可能会带来一定的性能开销,尽管第二次迭代的 Map 规模通常会小于原始 Map。

科威旅游管理系统
科威旅游管理系统

该软件是以php+MySQL进行开发的旅游管理网站系统。系统前端采用可视化布局,能自动适应不同尺寸屏幕,一起建站,不同设备使用,免去兼容性烦恼。系统提供列表、表格、地图三种列表显示方式,让用户以最快的速度找到所需行程,大幅提高效率。系统可设置推荐、优惠行程,可将相应行程高亮显示,对重点行程有效推广,可实现网站盈利。系统支持中文、英文,您还可以在后台添加新的语言,关键字单独列出,在后台即可快速翻译。

下载

方法二:高效的传统单次迭代循环

对于性能要求极高的场景,或者当 Map 包含的数据量非常大时,传统的单次迭代 for 循环通常能提供最优的性能。

核心思想

该方法通过一次遍历 Map 的所有 Entry 来实现。在遍历过程中,我们维护一个当前已知的最大值 maxValue 和一个存储所有与 maxValue 关联的键的列表 maxKeys。

实现步骤

  1. 初始化:创建一个空的 List 用于存储最大值对应的键,并初始化一个 maxValue 变量为 Integer.MIN_VALUE(或 Map 中第一个 Entry 的值)。
  2. 遍历 Map:迭代 map.entrySet() 中的每一个 Entry。
  3. 比较与更新
    • 如果当前 Entry 的值 e.getValue() 小于 maxValue,则说明它不是最大值,直接跳过。
    • 如果 e.getValue() 大于 maxValue,这表示我们找到了一个新的更大的最大值。此时,需要清空 maxKeys 列表,因为之前收集的键已不再是最大值对应的键。然后,更新 maxValue 为 e.getValue()。
    • 最后,将当前 Entry 的键 e.getKey() 添加到 maxKeys 列表中。

示例代码

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

public class MaxKeysCollector {

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

        List maxKeysLoop = new ArrayList<>();
        int maxValue = Integer.MIN_VALUE; // 初始化为最小整数值

        // 检查Map是否为空,避免在空Map上操作
        if (map.isEmpty()) {
            System.out.println("Map is empty, no max keys.");
            return;
        }

        for (Map.Entry e : map.entrySet()) {
            if (e.getValue() < maxValue) {
                // 当前值小于已知最大值,跳过
                continue;
            }
            if (e.getValue() > maxValue) {
                // 发现新的更大的最大值,清空旧的maxKeys
                maxKeysLoop.clear();
                maxValue = e.getValue(); // 更新最大值
            }
            // 当前值等于或大于最大值,添加到maxKeys
            maxKeysLoop.add(e.getKey());
        }

        System.out.println("传统循环结果: " + maxKeysLoop); // 预期输出: [first, third, fifth] (顺序可能不同)
    }
}

性能分析

这种方法只进行了一次 Map 遍历,因此在处理大量数据时,其性能通常优于 Stream API 的分组聚合方案。它避免了创建中间 Map 的开销,内存使用也更为高效。

选择合适的解决方案

  • Stream API 方案
    • 优点:代码简洁,声明式风格,可读性高,更符合 Java 8+ 的函数式编程范式。
    • 缺点:可能涉及多次迭代和中间数据结构创建,对于超大型 Map 性能可能略逊。
    • 适用场景:对代码优雅性和可读性要求较高,或 Map 数据量适中时。
  • 传统单次迭代循环方案
    • 优点:性能最优,只进行一次迭代,内存开销小。
    • 缺点:代码相对命令式,不如 Stream API 简洁。
    • 适用场景:对性能有严格要求,或处理超大型 Map 时。

总结

本文介绍了两种在 Java 8 中从 Map 提取所有最大值对应键列表的有效方法。Stream API 方案通过 groupingBy 和 max 提供了简洁的函数式实现,而传统单次迭代循环则在性能上表现更优。开发者应根据具体的应用场景、数据规模以及对代码可读性和性能的要求,选择最合适的实现方式。

热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

更多
string转int
string转int

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

443

2023.08.02

treenode的用法
treenode的用法

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

538

2023.12.01

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

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

17

2025.12.22

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

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

26

2026.01.06

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

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

75

2025.09.05

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

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

36

2025.11.16

golang map原理
golang map原理

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

60

2025.11.17

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

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

40

2025.11.27

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

31

2026.01.28

热门下载

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

精品课程

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

共23课时 | 2.9万人学习

C# 教程
C# 教程

共94课时 | 7.8万人学习

Java 教程
Java 教程

共578课时 | 52.3万人学习

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

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