Java 8:如何收集Map中所有具有相同最大值的键列表

Java 8:如何收集Map中所有具有相同最大值的键列表

本教程旨在解决一个常见的数据处理问题:从一个Map中,提取所有与最大整数值相关联的键(String)。特别地,当多个键共享同一个最大值时,我们期望能够收集到所有这些键的列表。

问题描述

假设我们有一个map,其中包含键值对。我们的目标是找到所有值等于map中最大值的键。

示例Map:

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

对于上述示例,Map中的最大值是50。键”first”和”third”都对应这个最大值。因此,我们期望的输出是一个包含[“first”, “third”]的列表。

现有尝试的局限性:

直接使用stream().max(Map.Entry.comparingByValue()).map(Map.Entry::getKey)通常只能返回一个键,即使存在多个键拥有相同的最大值。例如,它可能返回”third”(取决于流的内部顺序),但会忽略”first”。这不符合我们收集所有最大值键的需求。

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

解决方案一:使用Java 8 Stream API

此方法利用Java 8的Stream API进行多步处理。核心思想是首先根据值对Map的条目进行分组,然后从这些分组中找出与最大值对应的键列表。

实现思路:

将Map.Entry流转换为Map<Integer, List>,其中键是原始Map中的值,而值是所有对应这些值的键的列表。从这个新的Map中,找到键(即原始值)最大的那个条目。提取该条目中的值(即我们需要的键列表)。

代码示例:

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.*;public class MaxKeysCollector {    public static List getMaxKeysUsingStream(Map map) {        return map.entrySet()                .stream()                // 步骤1: 按值分组。键是原始值,值是所有对应这些值的键的列表。                // 例如: {50=[first, third], 10=[second], 20=[fourth]}                .collect(groupingBy(Map.Entry::getValue, mapping(Map.Entry::getKey, toList())))                .entrySet()                .stream()                // 步骤2: 找出新Map中键(即原始最大值)最大的条目。                .max(Map.Entry.<Integer, List>comparingByKey())                // 步骤3: 获取该条目的值,即包含所有最大值键的列表。                .orElseThrow(() -> new IllegalStateException("Map cannot be empty to find max keys."))                .getValue();    }    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);        List maxKeys = getMaxKeysUsingStream(map);        System.out.println("Stream API 方法获取的最大值键列表: " + maxKeys); // 预期输出: [first, third] 或 [third, first] (顺序不保证)    }}

代码解析:

groupingBy(Map.Entry::getValue, mapping(Map.Entry::getKey, toList())):这是核心操作。它首先将Map的条目按照它们的值(Map.Entry::getValue)进行分组。对于每个分组,它不是简单地收集Map.Entry,而是通过mapping(Map.Entry::getKey, toList())进一步处理,只收集键并将其放入一个列表中。max(Map.Entry.<Integer, List>comparingByKey()):在生成的新Map(Map<Integer, List>)上,我们再次创建一个流,并使用max操作符,通过比较键(即原始Map中的值)来找到最大的条目。orElseThrow().getValue():如果Map不为空,max操作会返回一个Optional<Map.Entry<Integer, List>>。orElseThrow()用于获取其内部值,然后getValue()提取出该条目中包含的键列表。

注意事项:

此方法涉及两次流迭代。第一次迭代用于分组,第二次迭代用于查找最大分组。虽然第二次迭代的Map通常会比原始Map小,但在数据量非常大的情况下,这可能会带来一定的性能开销。

解决方案二:单次迭代的命令式循环

对于追求极致性能的场景,一个传统的命令式循环通常是最高效的解决方案,因为它只需要对Map进行一次遍历。

实现思路:

初始化一个空列表maxKeys来存储结果。初始化maxValue为Integer.MIN_VALUE,用于跟踪当前遇到的最大值。遍历Map的每个条目。对于每个条目:如果当前条目的值小于maxValue,则跳过(它不可能是最大值)。如果当前条目的值大于maxValue,说明我们找到了一个新的最大值。此时,需要清空maxKeys列表,因为之前收集的键不再是最大值对应的键。更新maxValue为当前条目的值。将当前条目的键添加到maxKeys列表中。

代码示例:

import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;public class MaxKeysCollector {    public static List getMaxKeysUsingLoop(Map map) {        List maxKeys = new ArrayList();        int maxValue = Integer.MIN_VALUE; // 初始化为最小值        for (Map.Entry entry : map.entrySet()) {            int currentValue = entry.getValue();            String currentKey = entry.getKey();            if (currentValue  maxValue) {                // 找到了一个新的最大值,清空之前收集的键                maxKeys.clear();                maxValue = currentValue; // 更新最大值            }            // 如果 currentValue == maxValue,或者 currentValue > maxValue (清空后),则添加当前键            maxKeys.add(currentKey);        }        return maxKeys;    }    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", 60); // 添加一个更大的值测试        List maxKeysLoop = getMaxKeysUsingLoop(map);        System.out.println("命令式循环方法获取的最大值键列表: " + maxKeysLoop); // 预期输出: [fifth]        final Map map2 = new HashMap();        map2.put("first", 50);        map2.put("second", 10);        map2.put("third", 50);        List maxKeysLoop2 = getMaxKeysUsingLoop(map2);        System.out.println("命令式循环方法获取的最大值键列表 (原始示例): " + maxKeysLoop2); // 预期输出: [first, third]    }}

代码解析:

maxValue = Integer.MIN_VALUE;:确保任何Map中的值都能被正确识别为大于或等于初始最大值。if (currentValue maxValue) maxKeys.clear();:这是关键逻辑。当发现一个比当前maxValue更大的值时,意味着之前maxKeys中收集的所有键都不再是最大值对应的键了,因此需要清空列表。maxValue = currentValue;:更新maxValue为新的最大值。maxKeys.add(currentKey);:将当前键添加到maxKeys中。这个操作会在两种情况下发生:currentValue等于maxValue(收集所有相同最大值的键)。currentValue大于maxValue(在清空列表并更新maxValue之后,将新最大值对应的键添加进去)。

性能优势:

此方法只需要对Map进行一次迭代,因此在性能上通常优于Stream API的多步处理方法,尤其是在Map包含大量数据时。

总结与选择

本文提供了两种在Java 8中收集Map中所有具有相同最大值的键列表的方法:

Stream API方法: 简洁、声明性强,利用了groupingBy和max等高级Stream操作。代码可读性较高,但涉及多次迭代,可能在极端性能要求下略逊一筹。命令式循环方法: 性能最优,仅需单次迭代。逻辑清晰,易于理解其执行过程,适用于对性能有严格要求的场景。

在实际开发中,如果Map的数据量不是特别巨大,Stream API方法因其简洁性和声明性通常是更受欢迎的选择。但如果Map可能包含数十万甚至数百万条目,并且性能是首要考虑因素,那么单次迭代的命令式循环将是更明智的选择。

以上就是Java 8:如何收集Map中所有具有相同最大值的键列表的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/69245.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月12日 22:15:34
下一篇 2025年11月12日 23:02:28

相关推荐

  • CSS z-index与position:解决背景视频覆盖按钮的深度堆叠问题

    本文深入探讨了在网页设计中,背景视频可能覆盖其他元素(如按钮)的常见问题。通过分析css的z-index属性及其对position属性的依赖性,我们提供了详细的解决方案。文章将展示如何通过为元素设置适当的position属性来激活z-index,从而实现正确的元素堆叠顺序,确保按钮等交互元素始终可见…

    2025年12月23日
    000
  • 墨刀原型html如何改_修改墨刀原型导出的HTML文件【导出】

    需直接编辑导出的HTML源码进行定制化调整:一、修改页面标题和viewport;二、替换图片、CSS、JS等静态资源路径;三、在body底部注入自定义JavaScript逻辑;四、调整CSS响应式断点与容器宽度;五、移除墨刀水印。 如果您已使用墨刀完成原型设计并导出了HTML文件,但需要对导出结果进…

    2025年12月23日
    000
  • 解决Django表单验证失败后字段值清空的问题

    本文将指导您如何在Django中处理表单验证失败后字段值被清空的问题。通过正确使用Django模板标签渲染表单字段,确保用户提交的数据在验证失败后依然保留,无需用户重新输入,从而显著提升用户体验和表单的可用性。 在开发Web应用时,用户注册或数据提交表单是常见的交互环节。一个常见且影响用户体验的问题…

    2025年12月23日
    000
  • 如何匹配html_匹配HTML标签或内容的正则表达式【正则】

    正则表达式无法可靠解析嵌套HTML,但可按场景选用五种方案:一、匹配单闭合标签;二、非嵌套成对标签;三、提取属性值;四、处理注释与CDATA;五、.NET专属平衡组匹配单层嵌套。 如果您尝试使用正则表达式匹配HTML标签或其中的内容,但发现模式无法准确捕获目标结构,可能是由于HTML嵌套特性与正则表…

    2025年12月23日
    000
  • CSS悬停拉伸按钮的定位稳定性:盒模型深度解析与实践

    本文深入探讨了如何创建在悬停时能平滑拉伸但位置保持不变的CSS按钮。核心在于理解CSS盒模型,并通过精确平衡padding和margin的值,确保元素在不同状态下占据的总空间保持一致。文章将详细解释这一原理,并提供实用的代码示例和注意事项,帮助开发者实现稳定且用户体验友好的交互效果。 理解CSS盒模…

    2025年12月23日
    000
  • CSS表单输入框样式优化:解决聚焦位移与元素间距问题

    本教程旨在解决css表单开发中常见的输入框聚焦时产生位移以及表单元素间距难以控制的问题。通过深入分析边框属性对元素尺寸的影响,并利用父容器的margin属性实现元素间距,我们将展示如何创建稳定且布局合理的表单,显著提升用户体验。 在Web表单设计中,用户体验至关重要。其中,输入框的视觉反馈和布局稳定…

    2025年12月23日
    000
  • 如何隐藏按钮html5_HTML5按钮隐藏方法与控件可见性技巧【详解】

    HTML5提供五种隐藏按钮的方法:一、display: none彻底移除元素;二、visibility: hidden保留占位但不可见;三、hidden属性语义化隐藏;四、opacity+pointer-events实现透明禁用;五、aria-hidden配合CSS优化可访问性。 如果您希望在网页中…

    2025年12月23日
    000
  • Shadow DOM 样式与布局:Web Components 的封装机制解析

    本文深入探讨 web components 中 shadow dom 的样式规则与布局行为。我们将解析 shadow dom 内部样式定义、外部样式继承机制,以及 shadow host 元素与其内部内容如何共同决定最终渲染布局。通过示例代码,帮助开发者掌握 shadow dom 的样式封装特性,并…

    2025年12月23日
    000
  • 解决HTML按钮无响应:CSS选择器与事件交互深度解析

    本教程旨在解决html按钮显示正常但无法交互的问题,特别是悬停和点击事件失效的情况。文章将深入分析常见的css选择器误用(如`:hover`伪类与后代选择器的混淆)以及javascript事件监听的正确性,并提供一套系统的调试方法,帮助开发者诊断并修复此类前端交互故障,确保按钮功能按预期工作。 在网…

    2025年12月23日
    000
  • JavaScript中获取DOM节点X/Y位置的实用指南

    本教程详细阐述了在JavaScript中获取DOM节点X/Y位置的方法。针对Element节点,可直接使用`getBoundingClientRect()`。对于非Element节点(如文本节点),文章提供了两种策略:一是获取其父Element并计算位置,但需注意潜在的坐标偏移;二是利用`Range…

    2025年12月23日
    000
  • 如何通过键盘按键控制CSS动画的播放与暂停

    本教程详细介绍了如何利用javascript的键盘事件(keydown和keyup)来动态控制css动画的播放和暂停状态。我们将学习如何配置css动画使其无限循环并初始暂停,并通过javascript监听用户按键行为,实现按键时动画运行、松开按键时动画暂停的交互效果。 在现代网页设计中,动画是提升用…

    2025年12月23日
    000
  • html页面如何生成_动态生成HTML页面的技术与工具【技术】

    动态生成HTML页面需借助JavaScript操作DOM或模板字符串等技术实现:一、用document.createElement创建元素并append到容器;二、用ES6模板字符串插值后赋值innerHTML。 如果您需要在运行时根据数据或用户交互生成HTML内容,则可能是由于静态页面无法满足动态…

    2025年12月23日
    000
  • html5如何定义标题_HTML5文档定义各级标题标签方法【标题定义】

    必须使用至语义化标题标签构建层级结构,遵循唯一、逐级嵌套、不跳级、非空内容原则;可结合实现多维独立标题上下文;废弃;ARIA仅作可访问性补充。 如果您在编写HTML5文档时需要为内容设置结构化的标题层级,则必须使用语义化的标题标签来明确表达内容的重要性和层次关系。以下是HTML5中定义各级标题的具体…

    2025年12月23日
    000
  • 解决CSS中固定导航栏被绝对定位元素覆盖的问题:z-index的实践应用

    本文将探讨css中固定定位(position: fixed)导航栏被其他绝对定位(position: absolute)元素覆盖的常见问题。通过深入理解css的层叠上下文(stacking context)机制,我们将阐述为何会出现这种现象,并提供一种简洁有效的解决方案:通过合理设置z-index属…

    2025年12月23日
    000
  • 如何在表格中点击按钮高亮指定行

    本教程旨在解决在HTML表格中点击特定行内的按钮时,如何仅高亮显示该行的问题。文章将深入分析常见错误,例如重复绑定事件或不当的选择器使用,并提供基于jQuery的优化解决方案,通过一次性事件绑定和精确的元素定位,确保点击后只有目标行被正确高亮,提升用户交互体验和代码效率。 在构建交互式网页应用时,表…

    2025年12月23日
    000
  • 自己做的html不能运行怎么办_解自制html运行失败问题【技巧】

    首先检查文件扩展名是否为.html并确保保存为UTF-8编码;其次验证HTML结构包含、、、等完整标签且正确闭合;然后通过右键选择浏览器打开或拖入浏览器预览,确认使用file://协议运行;接着排查CSS、JS、图片等外部资源的路径是否正确,注意大小写和相对路径层级;最后按F12打开开发者工具,查看…

    2025年12月23日
    000
  • 基于键盘事件控制CSS动画的播放与暂停

    本文详细介绍了如何利用javascript的`keydown`和`keyup`事件,实现对css动画的精确播放与暂停控制。通过动态修改元素的`animation-play-state`属性,并结合`animation-iteration-count: infinite`确保动画循环播放,开发者可以为…

    2025年12月23日
    000
  • 优化点击区域:使用事件委托实现DIV内图标切换

    本教程旨在解决前端交互中,当需要通过点击父容器内任意区域来触发子元素(如图标)状态切换的问题。我们将探讨传统事件绑定方式的局限性,并详细介绍如何利用javascript的事件委托机制,结合`addeventlistener`和`event.target`属性,实现更灵活、高效且易于维护的交互逻辑,从…

    2025年12月23日
    000
  • 如何正确构建HTML结构以确保Bootstrap页脚自动下沉

    本教程旨在解决使用php `include` 和 bootstrap 5 时页脚与内容重叠的问题。核心在于纠正不正确的html结构,避免重复的“和` `标签,合理放置css和javascript引用,并移除可能导致布局冲突的`vh-100`类,确保页脚能根据内容动态下沉。 在Web开发中…

    2025年12月23日
    000
  • CSS Grid实现复杂不规则布局:告别传统表格限制

    本文深入探讨如何利用css grid布局实现传统html表格难以构建的复杂、不规则的网格布局,尤其适用于各列行高不一的视觉效果。通过详细解析css grid的核心属性,如网格定义、项目放置与跨度控制,并提供一个实际的代码示例,指导开发者高效构建动态且响应式的二维布局,从而摆脱对传统表格布局的束缚。 …

    2025年12月23日
    000

发表回复

登录后才能评论
关注微信