展开菜单
首页 精品内容 本月促销 装机必备 Windows PDF教程 macOS软件 IOS软件 Android AI 专题
全部分类

当前位置:

首页 > 编程开发 > EnumMap 初始化方式升级:从循环到 Stream 演进

EnumMap 初始化方式升级:从循环到 Stream 演进

本文探讨了在Java中高效使用EnumMap来管理枚举对之间复杂映射关系的不同初始化策略。通过对比《EffectiveJava》第二版和第三版中关于枚举状态转换映射的实现,详细介绍了传统的基于显式循环的初始化方法,以及现代Java利用StreamAPI进行声明式初始化的简洁高效方式。文章旨在帮助开发者理解并选择适合其项目需求的EnumMap初始化模式。

本文目录

    EnumMap 初始化策略演进:从显式循环到 Stream API

    本文探讨了在Java中高效使用EnumMap来管理枚举对之间复杂映射关系的不同初始化策略。通过对比《Effective Java》第二版和第三版中关于枚举状态转换映射的实现,详细介绍了传统的基于显式循环的初始化方法,以及现代Java利用Stream API进行声明式初始化的简洁高效方式。文章旨在帮助开发者理解并选择适合其项目需求的EnumMap初始化模式。

    在Java编程中,当我们需要将枚举类型作为键来存储数据时,EnumMap是比HashMap更优的选择。EnumMap是专门为枚举键设计的Map实现,它在内部使用数组存储值,因此具有极高的性能,并且是类型安全的。在处理涉及枚举状态转换等复杂映射场景时,EnumMap的优势尤为突出。

    考虑一个典型的场景:定义物质的不同相(固态、液态、气态)及其相互之间的转换。我们可以用一个外部枚举Phase表示物质的相,用一个嵌套枚举Transition表示相之间的转换。每个Transition实例都包含一个源相(from)和一个目标相(to)。我们的目标是构建一个映射,能够通过源相和目标相快速查找对应的Transition实例。例如,从液态到固态的转换是“凝固”(FREEZE)。

    传统初始化方法:《Effective Java》第二版实践

    在Java的早期版本,或者在不倾向于使用Stream API的场景下,初始化复杂的EnumMap通常采用显式的循环结构。这种方法通常涉及两层循环:外层循环用于初始化每个枚举键对应的内部EnumMap,内层循环则遍历所有转换实例,将其放入对应的映射中。

    以下是《Effective Java》第二版中可能采用的初始化方式:

    // Using a nested EnumMap to associate data with enum pairs
    public enum Phase {
        SOLID, LIQUID, GAS;
    
        public enum Transition {
            MELT(SOLID, LIQUID), FREEZE(LIQUID, SOLID),
            BOIL(LIQUID, GAS), CONDENSE(GAS, LIQUID),
            SUBLIME(SOLID, GAS), DEPOSIT(GAS, SOLID);
    
            final Phase src; // 源相
            final Phase dst; // 目标相
    
            Transition(Phase src, Phase dst) {
                this.src = src;
                this.dst = dst;
            }
    
            // 初始化相转换映射
            private static final Map> m =
                new EnumMap>(Phase.class);
            static {
                // 第一步:为每个源相初始化一个内部的EnumMap
                for (Phase p : Phase.values()) {
                    m.put(p, new EnumMap(Phase.class));
                }
                // 第二步:遍历所有转换实例,将其放入对应的内部EnumMap中
                for (Transition trans : Transition.values()) {
                    m.get(trans.src).put(trans.dst, trans);
                }
            }
    
            public static Transition from(Phase src, Phase dst) {
                return m.get(src).get(dst);
            }
        }
    }

    这种方法的优点是逻辑清晰、直观易懂。通过分步操作,我们可以清楚地看到Map是如何被构建和填充的。对于Java初学者或习惯命令式编程风格的开发者来说,这种方式的可读性较高。然而,其缺点是代码相对冗长,尤其是在映射关系更加复杂时,可能需要更多的循环和条件判断。

    现代初始化方法:《Effective Java》第三版实践

    随着Java 8引入Stream API,集合操作变得更加声明式和函数式。对于EnumMap的初始化,尤其是需要根据多个属性进行分组和映射的场景,Stream API提供了一种更为简洁高效的解决方案。

    以下是《Effective Java》第三版中采用的Stream API初始化方式:

    public enum Phase {
       SOLID, LIQUID, GAS;
    
       public enum Transition {
          MELT(SOLID, LIQUID), FREEZE(LIQUID, SOLID),
          BOIL(LIQUID, GAS), CONDENSE(GAS, LIQUID),
          SUBLIME(SOLID, GAS), DEPOSIT(GAS, SOLID);
    
          private final Phase from; // 源相
          private final Phase to;   // 目标相
    
          Transition(Phase from, Phase to) {
             this.from = from;
             this.to = to;
          }
    
          // 初始化相转换映射
          private static final Map>
             m = Stream.of(values()).collect(groupingBy(t -> t.from, // 按源相分组
             toMap(t -> t.to, t -> t, // 内部Map:键为目标相,值为转换实例
                (x, y) -> y,  // 合并函数:在键冲突时选择第二个值(此处不会发生冲突,但必须提供)
                () -> new EnumMap<>(Phase.class)))); // 内部Map的工厂:确保生成EnumMap
    
          public static Transition from(Phase from, Phase to)  {
             return m.get(from).get(to);
          }
       }
    }

    这段代码利用了Stream.of(values())将所有Transition实例转换为一个流。接着,collect()方法结合了两个重要的收集器:

    1. groupingBy(t -> t.from):这是一个外层收集器,它根据Transition实例的from(源相)属性进行分组,生成一个Map>。但在这里,它与第二个收集器结合使用。
    2. toMap(t -> t.to, t -> t, (x, y) -> y, () -> new EnumMap<>(Phase.class)):这是groupingBy的下游收集器,它作用于每个分组(即每个Phase对应的Transition列表)。
      • t -> t.to:指定内部Map的键是Transition实例的to(目标相)。
      • t -> t:指定内部Map的值是Transition实例本身。
      • (x, y) -> y:这是一个合并函数。当出现键冲突时(即同一个源相到同一个目标相存在多个Transition实例时),它定义了如何解决冲突。在此特定场景下,每个源相到目标相的转换是唯一的,因此这个合并函数实际上不会被调用,但toMap方法要求在提供Map工厂时必须提供此参数。
      • () -> new EnumMap<>(Phase.class):这是一个Map工厂,它确保了groupingBy生成的内部Map是EnumMap类型,而不是默认的HashMap,从而保留了EnumMap的性能优势。

    这种Stream API的初始化方式显著减少了代码行数,代码更加紧凑和声明式。它表达了“我们想要根据源相分组,然后在每个组内,根据目标相映射到转换实例”的意图,而不是“先创建这个,再遍历那个来填充”。

    两种方法的对比与选择

    • 可读性与简洁性: 传统循环方法在逻辑上更显式,对于不熟悉Stream API的开发者来说可能更容易理解。Stream API方法则更加简洁和函数式,一旦掌握其模式,就能快速理解其意图。
    • 性能: 对于枚举类型,EnumMap本身就提供了优异的性能。两种初始化方法在最终的运行时性能上差异不大,主要体现在初始化阶段。Stream API在内部优化上可能略有优势,但对于大多数应用而言,这不是决定性因素。
    • 代码风格与维护: Stream API代表了现代Java的编程范式,使用它可以使代码更具表达力。然而,如果团队成员对Stream API不熟悉,过度使用可能会降低代码的可维护性。

    总结

    无论是采用传统的显式循环还是现代的Stream API,核心思想都是为了高效地初始化EnumMap,以实现枚举对之间的复杂映射。在实际项目中,选择哪种初始化方法应基于以下考量:

    1. 团队熟悉度: 如果团队成员普遍熟悉Stream API,那么采用Stream API可以提升代码质量和简洁性。反之,传统循环可能更安全。
    2. 复杂性: 对于简单的映射,两种方法差异不大。但对于涉及多层分组、过滤或转换的复杂映射,Stream API往往能提供更优雅、更紧凑的解决方案。
    3. 项目规范: 遵循项目或团队既定的代码风格和规范。

    总之,EnumMap是处理枚举键映射的强大工具,而Java语言的发展为我们提供了多种初始化其复杂结构的方式。理解并灵活运用这些方法,将有助于我们编写出更高效、更可维护的Java代码。

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发
    相关文章 更多
    精品专题 更多
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    macOS软件

    正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

    IOS软件

    正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

    AI

    正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

    Mac软件 更多
    Aperty macOS版
    Aperty macOS版

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    火山引擎 网页版
    火山引擎 网页版

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    立刻MV 网页版
    立刻MV 网页版

    立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

    蛙蛙写作 网页版
    蛙蛙写作 网页版

    蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

    讯飞智作 网页版
    讯飞智作 网页版

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    超级简历WonderCV 网页版
    超级简历WonderCV 网页版

    超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

    音述AI 网页版
    音述AI 网页版

    音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

    AionClaw macOS版
    AionClaw macOS版

    AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

    Loomy macOS版
    Loomy macOS版

    Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

    AirBuddy 3 macOS版
    AirBuddy 3 macOS版

    AirBuddy 3 是面向 macOS 的蓝牙外设增强工具,可集中查看 AirPods、Beats 与苹果设备电量,提供快速连接、播放控制、电量提醒、桌面小组件和多台 Mac 外设接力等功能。

    AirServer macOS版
    AirServer macOS版

    AirServer macOS版可把 Mac 转换为无线投屏接收端,通过 AirPlay 或 Google Cast 接收手机、平板和电脑画面,并支持多设备同时连接、高清镜像及会话录制,适合家庭娱乐、课堂教学、会议演示和应用展示。

    AnyDesk macOS版
    AnyDesk macOS版

    AnyDesk macOS版是一款适用于远程办公、设备维护和客户支持的远程桌面工具,可连接并操作异地计算机,支持文件传输、无人值守访问、会话权限控制及跨平台协作。

    WINDOWS 更多
    讯飞绘文 网页版
    讯飞绘文 网页版

    讯飞绘文网页版是科大讯飞推出的AI图文创作与内容运营工具,覆盖热点选题、文章生成、稿件校对、智能配图、排版发布和数据复盘等环节,适合自媒体创作者及内容团队在线使用。

    Maya(Autodesk Maya) Windows版
    Maya(Autodesk Maya) Windows版

    Autodesk Maya 是面向影视、电视、动画和游戏行业的专业三维制作软件,集多边形与 NURBS 建模、角色绑定、关键帧和动作捕捉动画、Bifrost 特效模拟、材质开发及 Arnold 渲染于一体,

    Aperty Windows版
    Aperty Windows版

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    火山引擎 网页版
    火山引擎 网页版

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    立刻MV 网页版
    立刻MV 网页版

    立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

    蛙蛙写作 网页版
    蛙蛙写作 网页版

    蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

    讯飞智作 网页版
    讯飞智作 网页版

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    超级简历WonderCV 网页版
    超级简历WonderCV 网页版

    超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

    音述AI 网页版
    音述AI 网页版

    音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

    AionClaw Windows版
    AionClaw Windows版

    AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

    Loomy Windows版
    Loomy Windows版

    Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

    AirServer Windows版
    AirServer Windows版

    AirServer Windows版可把电脑变成AirPlay、Google Cast和Miracast无线投屏接收端,适合会议演示、课堂教学及家庭大屏分享。发送设备通常无需另装客户端,并可同时接收和智能排列多个镜像会话。