Java代码重构:通过HashMap和forEach优化多列表循环判断

Java代码重构:通过HashMap和forEach优化多列表循环判断

本教程旨在解决Java程序中因使用多个列表和冗余循环进行数据查找和分配而导致的低效与维护难题。通过引入HashMap和HashSet这两种更优的数据结构,我们将展示如何将繁琐的多个for循环精简为一个简洁的forEach操作,从而显著提升代码的可读性、可维护性和执行效率,尤其适用于需要将特定值映射到不同类别的场景。

1. 问题背景与现有实现分析

在许多应用场景中,我们可能需要将一组特定的数据(如邮政编码)分配给不同的实体(如人员)。一个常见的、但效率低下的做法是为每个实体创建一个独立的列表来存储其对应的所有数据项,然后通过多个独立的循环来检查输入值是否属于某个实体的列表。

考虑以下Java代码片段,它展示了为不同人员(John, Mark, Luna)分配邮政编码的初始实现:

import java.util.ArrayList;import java.util.Arrays;import java.util.List;import java.util.Scanner;public class ZipCodeAssigner {    public static void main(String[] args) {        Scanner scnr = new Scanner(System.in);        // 为每个人员创建独立的邮政编码列表        List pe1a = new ArrayList(Arrays.asList(1547, 1549)); // John的邮编        List pe1c = new ArrayList(Arrays.asList(1606, 2458)); // Mark的邮编        // 假设还有 pe1d, pe1e 等更多列表...        System.out.print("Enter the zipcode: ");        int zipCodeNumber = 0;        if (scnr.hasNextInt()) {            zipCodeNumber = scnr.nextInt();        } else {            System.out.println("Please enter a valid ZipCode:");            scnr.close();            return; // 退出程序        }        // 使用多个独立的循环进行查找        for (Integer zip : pe1a) {            if (zipCodeNumber == zip) {                System.out.println("John");                break; // 找到后可以提前退出            }        }        for (Integer zip : pe1c) {            if (zipCodeNumber == zip) {                System.out.println("Mark");                break; // 找到后可以提前退出            }        }        // 假设还有针对 pe1d, pe1e 等列表的更多循环...        scnr.close();    }}

这种实现方式存在以下几个主要问题:

代码冗余: 每增加一个实体,就需要新增一个列表和一个相应的循环,导致大量重复代码。维护困难: 当需要修改或添加分配规则时,必须修改多个地方,容易出错。效率低下: 尽管单个列表查找效率尚可,但随着列表数量的增加,整体查找时间会线性增长。可读性差: 随着逻辑的扩展,代码变得难以理解和管理。

2. 优化方案:选择合适的数据结构

为了解决上述问题,核心在于选择一个能够更好地表示“人员-邮编集合”这种映射关系的数据结构。HashMap 是一个理想的选择,它允许我们通过一个键(Key)来快速查找对应的值(Value)。

在这里,我们可以将:

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

键 (Key):设为人员的姓名(String 类型)。值 (Value):设为该人员所负责的所有邮政编码的集合。

对于值的集合,HashSet 是比 ArrayList 更优的选择,原因如下:

查找效率: HashSet 内部基于哈希表实现,其 contains() 方法的平均时间复杂度为 O(1),这意味着无论集合中有多少个元素,查找速度都非常快。而 ArrayList 的 contains() 方法需要遍历整个列表,时间复杂度为 O(n)。唯一性: HashSet 自动保证元素的唯一性,虽然在这个特定场景下邮编通常不会重复分配给同一个人,但这是其固有的优点。

下面是使用 HashMap<String, HashSet> 重构数据结构的代码:

import java.util.Arrays;import java.util.HashMap;import java.util.HashSet;import java.util.Scanner;public class OptimizedZipCodeAssigner {    public static void main(String[] args) {        Scanner scnr = new Scanner(System.in);        // 使用 HashMap 存储人员及其对应的邮政编码集合        HashMap<String, HashSet> zipcodeMap = new HashMap();        // 初始化数据:将人员姓名作为键,其邮编集合作为值        zipcodeMap.put("John", new HashSet(Arrays.asList(1547, 1549)));        zipcodeMap.put("Mark", new HashSet(Arrays.asList(1606, 2458)));        zipcodeMap.put("Luna", new HashSet(Arrays.asList(3058, 2214, 3895)));        // 添加更多人员和邮编只需在此处put新的键值对即可        System.out.print("Enter the zipcode: ");        int zipCodeNumber = 0;        if (scnr.hasNextInt()) {            zipCodeNumber = scnr.nextInt();        } else {            System.out.println("Please enter a valid ZipCode:");            scnr.close();            return;        }        // ... (接下来的查找逻辑将在下一节介绍)        scnr.close();    }}

3. 简化查找逻辑:告别冗余循环

有了 HashMap 这种高效的数据结构后,我们可以将原来多个 for 循环替换为一个简洁的 forEach 迭代,遍历 HashMap 中的每个键值对

HashMap 的 forEach 方法接受一个 BiConsumer 类型的 lambda 表达式,允许我们对每个键值对执行指定的操作。在我们的场景中,这个操作就是检查当前人员的 HashSet 中是否包含输入的邮政编码。

// ... (接续 OptimizedZipCodeAssigner 的 main 方法)        // 使用 forEach 遍历 HashMap,查找匹配的邮编        boolean found = false; // 用于标记是否找到匹配项        for (java.util.Map.Entry<String, HashSet> entry : zipcodeMap.entrySet()) {            String personName = entry.getKey();            HashSet zipcodes = entry.getValue();            if (zipcodes.contains(zipCodeNumber)) {                System.out.println(personName);                found = true;                // 如果只需要找到第一个匹配项就停止,可以使用Stream API的findFirst                // 但对于所有匹配项都打印,或者需要一个标记,for-each循环或forEach是合适的                break; // 找到一个匹配项后,如果只关心第一个,可以跳出循环            }        }        if (!found) {            System.out.println("No person assigned to this zipcode.");        }        // 或者使用更简洁的lambda表达式 forEach (如果不需要提前跳出循环)        // 注意:forEach无法直接实现break,如果需要找到第一个并停止,Stream API更合适        /*        zipcodeMap.forEach((personName, zipcodes) -> {            if (zipcodes.contains(zipCodeNumber)) {                System.out.println(personName);            }        });        */// ... (main 方法结束)

在这个 for-each 循环中:

代码小浣熊 代码小浣熊

代码小浣熊是基于商汤大语言模型的软件智能研发助手,覆盖软件需求分析、架构设计、代码编写、软件测试等环节

代码小浣熊 51 查看详情 代码小浣熊 zipcodeMap.entrySet() 返回 HashMap 中所有键值对的集合。循环遍历每个 Entry 对象,从中获取 personName (键) 和 zipcodes (值)。zipcodes.contains(zipCodeNumber) 利用 HashSet 的高效查找特性,判断当前人员的邮编集合是否包含输入的邮编。如果找到匹配项,则打印对应的 personName。

4. 完整示例代码

以下是整合了数据结构优化和查找逻辑简化的完整Java教程代码:

import java.util.ArrayList;import java.util.Arrays;import java.util.HashMap;import java.util.HashSet;import java.util.List;import java.util.Scanner;public class OptimizedZipCodeAssignerTutorial {    public static void main(String[] args) {        Scanner scnr = new Scanner(System.in);        // 1. 优化数据结构:使用 HashMap 存储人员及其对应的邮政编码集合        // 键:String (人员姓名)        // 值:HashSet (该人员负责的所有邮政编码)        HashMap<String, HashSet> zipcodeAssignmentMap = new HashMap();        // 初始化数据        zipcodeAssignmentMap.put("John", new HashSet(Arrays.asList(1547, 1549)));        zipcodeAssignmentMap.put("Mark", new HashSet(Arrays.asList(1606, 2458)));        zipcodeAssignmentMap.put("Luna", new HashSet(Arrays.asList(3058, 2214, 3895)));        // 轻松添加更多人员和邮编,无需修改核心逻辑        zipcodeAssignmentMap.put("Alice", new HashSet(Arrays.asList(1001, 1002)));        System.out.print("Enter the zipcode: ");        int zipCodeNumber = 0;        // 输入验证        if (scnr.hasNextInt()) {            zipCodeNumber = scnr.nextInt();        } else {            System.out.println("Invalid input. Please enter a valid integer ZipCode.");            scnr.close();            return;        }        // 2. 简化查找逻辑:告别冗余循环,使用单个循环遍历 HashMap        boolean foundAssignment = false;        // 遍历 HashMap 的 entrySet 来获取键值对        for (java.util.Map.Entry<String, HashSet> entry : zipcodeAssignmentMap.entrySet()) {            String personName = entry.getKey();            HashSet assignedZipcodes = entry.getValue();            // 利用 HashSet 的 O(1) 平均时间复杂度进行高效查找            if (assignedZipcodes.contains(zipCodeNumber)) {                System.out.println("Assigned to: " + personName);                foundAssignment = true;                // 如果一个邮编只分配给一个人,找到后即可退出循环                break;             }        }        if (!foundAssignment) {            System.out.println("No person found for zipcode: " + zipCodeNumber);        }        scnr.close(); // 关闭 Scanner 资源    }}

5. 注意事项与最佳实践

输入验证: 在实际应用中,始终要对用户输入进行严格的验证,确保其符合预期格式和业务规则。本教程示例中包含了基本的 hasNextInt() 检查。

错误处理: 对于未找到匹配项的情况,应给出明确的用户反馈,而不是静默失败。

性能考量: HashMap 和 HashSet 在大多数情况下提供了优异的平均性能(O(1) 查找),但在极端哈希冲突的情况下,性能可能退化到 O(n)。然而,对于整数和字符串等常见类型,这种情况很少发生。

可扩展性: 这种基于 HashMap 的设计极大地提高了代码的可扩展性。未来如果需要添加新的负责人或修改邮编分配,只需修改 zipcodeAssignmentMap 的初始化部分,而无需触碰核心查找逻辑。

代码可读性: 重构后的代码逻辑更清晰,意图更明确,易于理解和维护。

Java 8 Stream API: 对于更复杂的查找或聚合需求,Java 8 的 Stream API 提供了更强大的功能。例如,如果需要找出所有负责该邮编的人员列表,可以这样做:

List responsiblePersons = zipcodeAssignmentMap.entrySet().stream()    .filter(entry -> entry.getValue().contains(zipCodeNumber))    .map(java.util.Map.Entry::getKey)    .collect(java.util.Collectors.toList());if (!responsiblePersons.isEmpty()) {    System.out.println("Responsible persons: " + responsiblePersons);} else {    System.out.println("No person found for zipcode: " + zipCodeNumber);}

这种方式在某些场景下更为函数式和简洁。

6. 总结

通过本教程,我们学习了如何将Java代码中冗余的、基于多个列表和循环的数据查找逻辑,重构为使用 HashMap 和 HashSet 的高效、简洁实现。这种优化不仅解决了代码重复、维护困难和效率低下的问题,还显著提升了代码的可读性和可扩展性。在处理类似数据映射和查找的场景时,选择合适的数据结构是构建健壮、高性能应用程序的关键。

以上就是Java代码重构:通过HashMap和forEach优化多列表循环判断的详细内容,更多请关注创想鸟其它相关文章!

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

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月5日 14:23:18
下一篇 2025年11月5日 14:24:46

相关推荐

  • 使用 Django 和 HTMX 创建 To-Do 应用程序 – 使用 TDD 添加 Todo 模型部分

    this is part two of our series on building a todo application with htmx and django. click here to view part 1. In Part 2, we’ll create the todo …

    2025年12月13日
    000
  • 在 Python 中创建 Stripe 测试数据

    本教程演示如何通过一个简单的python脚本,快速在stripe沙盒环境中生成测试数据,用于构建基于supabase和openai的ai聊天机器人。此方法避免了复杂命令行工具的安装,降低了学习门槛。 许多AI数据课程需要预先加载的测试数据,但Stripe沙盒环境并未提供。虽然可以使用命令行工具加载示…

    2025年12月13日
    000
  • 最小最大和 – HackerRank 问题解决

    HackerRank 的最小最大和挑战 本文将指导您解决 HackerRank 的“最小最大和”算法挑战。此挑战需要您计算给定整数数组中任意四个元素的最小和与最大和。我们将探讨 Python 和 C 语言的解决方案。 问题描述 给定一个包含 n 个整数的数组,计算该数组中任意四个元素的最小和与最大和…

    2025年12月13日
    000
  • 在浏览器中轻松运行Python程序

    微软开源的markitdown项目,将office文件转换为markdown格式,迅速成为github热门项目。但其python程序特性限制了非技术用户的易用性。本文介绍如何利用webassembly技术,结合pyodide在浏览器中直接运行markitdown,解决这一问题。 Pyodide是一个…

    2025年12月13日
    000
  • 如何在地图中追踪步骤,代码降临 ay 6

    advent of code 2024: day 6 – guard patrol optimization I’m a bit behind on my Advent of Code challenges this year due to unforeseen circum…

    2025年12月13日
    000
  • Python 最佳实践:编写简洁且可维护的代码

    Python以其简洁性和可读性而闻名,深受初学者和资深开发者的喜爱。然而,编写干净、易于维护的代码需要超越基本语法。本文将探讨一些提升Python代码质量的关键最佳实践。 PEP 8规范的力量 PEP 8是Python的代码风格指南,遵循它能显著提升代码的可读性和可维护性。以下是一些核心原则: # …

    2025年12月13日
    000
  • 新手常见的 Python 面试问题

    本文将探讨10个常见的Python面试问题,帮助应届生顺利应对面试。 1. 解释型语言的概念 解释型语言由解释器逐行执行,其动态特性深受开发者青睐,便于调试和开发,并提供即时反馈。 2. Python的主要特性 立即学习“Python免费学习笔记(深入)”; Python是一款功能强大的跨平台编程语…

    2025年12月13日
    000
  • 使用 DQN 构建国际象棋代理

    我最近尝试用dqn构建一个国际象棋ai代理。 任何了解DQN和国际象棋的人都会告诉你这是个不太现实的想法。 确实如此,但作为一名初学者,我依然乐于尝试。本文将分享我的经验和心得。 环境理解 在实现代理之前,我需要熟悉环境并创建一个自定义包装器,以便在训练过程中与代理交互。 我使用了kaggle_en…

    2025年12月13日 好文分享
    000
  • Python While 循环教程 #Day3

    This Python code implements several functions using while loops to solve various number-related problems: 1. Armstrong Number: An Armstrong number is …

    2025年12月13日
    000
  • 入门级 Bing 壁纸刮刀

    构建 Bing 壁纸自动下载器:准备工作与代码实现 本指南将引导您创建一个简单的 Python 脚本,自动下载 Bing 的每日壁纸。我们将分析 Bing 壁纸网页元素和 API,并提供完整的代码示例。 一、关键组件分析 Bing 壁纸 API: Bing 提供了一个 JSON API 接口,用于访…

    2025年12月13日
    000
  • 系统设计的重要元素和要记住的事情

    系统设计是构建满足特定需求的系统架构、模块、接口和数据的过程,是软件开发中至关重要的环节,直接影响系统的可扩展性、可维护性、可靠性和性能。本文将深入探讨关键的最佳实践,并辅以代码示例。 1. 深入理解问题领域 在编码之前,务必透彻理解待解决的问题,这包括: 用户需求: 明确系统使用者、目标和工作流程…

    2025年12月13日
    000
  • 只需几分钟即可在 Ubuntu 上设置 Anaconda:简化您的 AI 工作流程

    在数据科学、机器学习或人工智能项目管理中,选择合适的工具至关重要。anaconda是一个强大的python库,简化了包、依赖项和环境的管理。无论是资深ai模型开发者,还是数据科学领域的新手,anaconda都能提供良好的开端。 本指南将逐步指导您如何在Ubuntu上使用安装脚本安装Anaconda,…

    2025年12月13日 好文分享
    000
  • 创建令人惊叹的全景变得简单

    全景摄影:捕捉广阔视野的艺术 全景照片以其令人叹为观止的广阔视野和细节展现,在摄影领域独树一帜。然而,传统全景照片制作过程繁琐复杂,需要精确对齐和耗时的后期拼接。 现在,有了Luminar Neo的AI照片拼接功能,这一切都将变得简单易行。这款革命性软件让每个人都能轻松创作出令人惊艳的全景杰作,无需…

    2025年12月13日
    000
  • 探索 Python 编程世界

    python:程序员挚爱的多功能编程语言 Python凭借其简洁易懂的语法和强大的功能,近年来已成为备受青睐的编程语言。无论是编程新手还是经验丰富的开发者,都能轻松上手Python并从中受益。本文将深入探讨Python的核心特性、应用领域以及它广受欢迎的原因。 为什么选择Python? 易读易用: …

    2025年12月13日
    000
  • 了解 Python 术语:模块、包、库和框架

    学习编程语言时,理解专业术语至关重要。Python中的模块(module)、包(package)、库(library)和框架(framework)经常出现,但它们之间的区别并不总是清晰明了。本文旨在阐明这些概念,并通过示例说明其差异。 1. 模块 Python模块是一个包含Python代码的单个文件…

    2025年12月13日
    000
  • IRIS-RAG-Gen:由 IRIS 矢量搜索提供支持的个性化 ChatGPT RAG 应用程序

    iris-rag-gen:一款基于Iris的检索增强生成(RAG)应用 大家好!本文将介绍我的应用iris-rag-gen,这是一款利用iris矢量搜索功能的生成式ai检索增强生成(rag)应用。它结合了streamlit web框架、langchain和openai,能够个性化chatgpt的交互…

    2025年12月13日 好文分享
    000
  • 在 Python 请求库中使用 XML

    本文介绍如何使用Python的requests库和xml.etree.ElementTree模块解析XML数据。XML(可扩展标记语言)用于存储结构化数据。 常见的XML应用包括站点地图和RSS订阅。 以下是一个XML文件示例: belgian waffles $5.95 two of our fa…

    2025年12月13日
    000
  • 掌握 Pytest Monkeypatch:简化您的测试

    当涉及到 python 测试时,确保可靠且隔离的测试至关重要。一项常见的挑战是如何在测试期间模拟或修改对象和函数的行为。这就是 pytest monkeypatch 装置的闪光点。它提供了一种灵活的方法来在测试期间动态替换部分代码。 在这篇博客中,我们将探讨 monkeypatch 的强大功能、它为…

    好文分享 2025年12月13日
    000
  • 计算令牌:对细节进行排序

    高效管理OpenAI微调成本:精准计算令牌数量 在OpenAI进行模型微调时,精确计算令牌数量至关重要,这不仅关系到模型训练效果,更直接影响到成本控制。 就像一位面对大量信息需要精准分类的员工一样,我们必须有效管理资源。 使用tiktoken库,我们可以轻松计算文本数据的令牌数量,确保在OpenAI…

    2025年12月13日
    000
  • ETL 中多少自动化才算是太多自动化

    ETL(提取、转换、加载)流程自动化是一把双刃剑。它能简化重复性工作,提高效率,降低人为错误率;但过度自动化却可能适得其反,导致流程过于复杂、僵化,难以维护。 如何找到自动化与人工干预的最佳平衡点?本文将探讨这一问题。 自动化的优势 设想一下:您的数据项目需要处理来自不同来源的海量数据,例如应用程序…

    2025年12月13日
    000

发表回复

登录后才能评论
关注微信