Effective Java~37. 用EnumMap 代替序数索引

       有时可能会看到使用 ordinal 方法(条目 35)来索引到数组或列表的代码。 例如,考虑一下这个简单的类来代表一种植物:

class Plant {enum LifeCycle { ANNUAL, PERENNIAL, BIENNIAL }final String name;final LifeCycle lifeCycle;Plant(String name, LifeCycle lifeCycle) {this.name = name;this.lifeCycle = lifeCycle;}@Override public String toString() {return name;}
}

        现在假设你有一组植物代表一个花园,想要列出这些由生命周期组织的植物 (一年生,多年生,或双年生)。为此,需要构建三个集合,每个生命周期作为一个,并遍历整个花园,将每个植物放置在适当的集合中。

// Using ordinal() to index into an array - DON'T DO THIS!
Set<Plant>[] plantsByLifeCycle = (Set<Plant>[]) new Set[Plant.LifeCycle.values().length];
for (int i = 0; i < plantsByLifeCycle.length; i++)plantsByLifeCycle[i] = new HashSet<>();for (Plant p : garden)plantsByLifeCycle[p.lifeCycle.ordinal()].add(p);// Print the results
for (int i = 0; i < plantsByLifeCycle.length; i++) {System.out.printf("%s: %s%n",Plant.LifeCycle.values()[i], plantsByLifeCycle[i]);
}

        这种方法是有效的,但充满了问题。 因为数组不兼容泛型(条目 28),程序需要一个未经检查的转换,并且不会干净地编译。 由于该数组不知道索引代表什么,因此必须手动标记索引输出。 但是这种技术最严重的问题是,当你访问一个由枚举序数索引的数组时,你有责任使用正确的 int 值; int 不提供枚举的类型安全性。 如果你使用了错误的值,程序会默默地做错误的事情,如果你幸运的话,抛出一个 ArrayIndexOutOfBoundsException 异常。

        有一个更好的方法来达到同样的效果。 该数组有效地用作从枚举到值的映射,因此不妨使用 Map 。 更具体地说,有一个非常快速的 Map 实现,设计用于枚举键,称为 java.util.EnumMap 。 下面是当程序重写为使用EnumMap 时的样子:

// Using an EnumMap to associate data with an enum
Map<Plant.LifeCycle, Set<Plant>> plantsByLifeCycle = new EnumMap<>(Plant.LifeCycle.class);for (Plant.LifeCycle lc : Plant.LifeCycle.values())plantsByLifeCycle.put(lc, new HashSet<>());for (Plant p : garden)plantsByLifeCycle.get(p.lifeCycle).add(p);System.out.println(plantsByLifeCycle);

        这段程序更简短,更清晰,更安全,运行速度与原始版本相当。 没有不安全的转换; 无需手动标记输出,因为map 键是知道如何将自己转换为可打印字符串的枚举; 并且不可能在计算数组索引时出错。 EnumMap 与序数索引数组的速度相当,其原因是 EnumMap 内部使用了这样一个数组,但它对程序员的隐藏了这个实现细节,将 Map 的丰富性和类型安全性与数组的速度相结合。 请注意, EnumMap 构造方法接受键类Class 型的 Class 对象:这是一个有限定的类型令牌(bounded type token),它提供运行时的泛型类型信息(条目 33)。

        通过使用 stream (条目 45)来管理 Map ,可以进一步缩短以前的程序。 以下是最简单的基于 stream 的代码,它们在很大程度上重复了前面示例的行为:

// Naive stream-based approach - unlikely to produce an EnumMap!
System.out.println(Arrays.stream(garden).collect(groupingBy(p -> p.lifeCycle)));

        这个代码的问题在于它选择了自己的 Map 实现,实际上它不是 EnumMap ,所以它不会与显式 EnumMap 的版本的空间和时间性能相匹配。 为了解决这个问题,使用 Collectors.groupingBy 的三个参数形式的方法,它允许调用者使用 mapFactory 参数指定 map 的实现:

// Using a stream and an EnumMap to associate data with an enum
System.out.println(Arrays.stream(garden).collect(groupingBy(p -> p.lifeCycle,() -> new EnumMap<>(LifeCycle.class), toSet())));

        这样的优化在像这样的示例程序中是不值得的,但是在大量使用 Map 的程序中可能是至关重要的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/496153.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python操作MSSQL

Python连接SQL Server数据库 - pymssql使用基础&#xff1a;https://www.cnblogs.com/baiyangcao/p/pymssql_basic.html 廖雪峰官网 之 Python 访问数据库&#xff08;SQLLite / MySQL / SQLAlchemy&#xff09; pymssql examples &#xff1a;http://pymssql.org/en/stable/p…

联想linux笔记本评测,联想(lenovo)G460AL-ITH Linux笔记本电脑接口评测-ZOL中关村在线...

模具和外观的“革新”让我们见识到不一样的联想G460&#xff0c;而在整机的接口扩展能力方面依旧主打实用性。机身左侧从左至右依次是安全锁孔、散热孔、RJ-45以太网接口、VGA视频输出接口、USB2.0接口、e-SATA接口(兼容USB2.0)、Express Card卡槽和HDMI高清视频输出接口。与前…

联合国召开会议讨论“杀手机器人”问题

来源&#xff1a;中国科学报 作者&#xff1a;赵熙熙来自29个国家的57位科学家日前呼吁联合抵制一所韩国大学&#xff0c;因为设立在该校的一个新的中心旨在利用人工智能强化国家安全。人工智能科学家表示&#xff0c;该大学正在开发自主武器&#xff0c;又称“杀手机器人”&a…

Effective Java~38. 用接口模拟可扩展的enum

使用枚举类型有一个很好的方法来实现这种效果。基本思想是利用枚举类型可以通过为 opcode 类型定义一个接口&#xff0c;并实现任意接口。 // Emulated extensible enum using an interface public interface Operation {double apply(double x, double y); } public enum Ba…

C语言的叙述大小写字母e1相同,第1、2章C语言基础练习题

第1章 C语言基础 第2章 顺序结构 练习题 学号&#xff1a; 姓名&#xff1a;单选&#xff1a;1. 当代电子计算机能够自动地处理指定的问题是因为( )。A. 计算机是电动的B. 有解决该问题的计算机程序 C. 事先存储了解决该问题的程序 D. 以上都不是2. C语言源程序的基本单位是( )…

咱也开始玩z-blog了

目前来讲&#xff0c;国内的个人网站基本上用wordPress于z-blog的比较多&#xff0c;wordPress用PHP开发的&#xff0c;z-blog用的是asp&#xff0c;鉴于PHP空间相对asp对一些&#xff0c;维护起来也比asp麻烦一点&#xff0c;众多个人站长中&#xff0c;相信看得懂一点asp的比…

Python 执行 shell命令 的几个方法小结

参考&#xff1a;https://blog.csdn.net/ronnyjiang/article/details/53333538 Python 执行 shell 命令 Python 可以执行 shell 命令的相关 模块 和 函数 有&#xff1a; os.systemos.spawnos.popen --- 废弃popen2.* --- 废弃commands.* --- 废弃&#x…

linux离线安装docker,centos离线安装docker

1.下载依赖包提取码: 3tus2. 先安装如下rpm依赖文件audit-libs-python-2.8.4-4.el7.x86_64.rpmcheckpolicy-2.5-8.el7.x86_64.rpmlibcgroup-0.41-20.el7.x86_64.rpmlibseccomp-2.3.1-3.el7.x86_64.rpmlibsemanage-python-2.5-14.el7.x86_64.rpmpolicycoreutils-2.5-29.el7.x86…

Effective Java~42. Lambda 优于匿名类

在 Java 8 中&#xff0c;添加了函数式接口&#xff0c; lambda 表达式和方法引用&#xff0c;以便更容易地创建函数对象。下面是一段代码片段&#xff0c;按照字符串长度顺序对列表进行排序&#xff0c;使用匿名类创建排序的比较方法 &#xff08;强制排序顺序&#xff09;&am…

Python 远程部署利器 Fabric2 模块

fabric 官网英文文档&#xff1a;http://www.fabfile.org/ 《Python自动化运维技术与最佳实践》 如何用 Fabric 实现无密码输入提示的远程自动部署&#xff1a; fabric实现远程操作和部署&#xff1a; 简介 Fabric 是一个 Python 的库&#xff0c;同时它也是一个命令行工具。…

【转】近期Coolite控件的技术点总结

1。Coolite下如何自定义控件样式表Code1<style type"text/css"> 2 .x-grid3-td-fullName .x-grid3-cell-inner {}{ 3 font-family:tahoma, verdana; 4 display:block; 5 font-weight:normal; 6 font-style…

Anaconda 完全入门指南

From&#xff1a;https://www.jianshu.com/p/eaee1fadc1e9 Anaconda官网&#xff1a;https://www.anaconda.com/ Anaconda 官网 文档&#xff1a;http://docs.anaconda.com/anaconda/user-guide Anaconda介绍、安装及使用教程&#xff1a;https://zhuanlan.zhihu.com/p/32925…

Effective Java~43. 方法引用优于Lambda

Java 提供了一种生成函数对象的方法&#xff0c;比 lambda 还要简洁&#xff0c;那就是&#xff1a;方法引用&#xff08; method references&#xff09;。下面是一段程序代码片段&#xff0c;它维护一个从任意键到整数值的映射。如果将该值解释为键的实例个数&#xff0c;则该…

linux资源使用统计指南,指南:工作量分析文档

指南&#xff1a;工作量分析文档工作量分析文档工作量分析文档用于在不同的性能测试中确定要使用的变量并定义变量值&#xff0c;利用这些性能测试可以模拟主角特征、最终用户业务功能(用例)、负载和容量。主题软件质量要从不同的维度来进行评估&#xff0c;其中包括可靠性、功…

linux 下修改日期和时间

我们一般使用“date -s”命令来修改系统时间。比如将系统时间设定成2009年11月13日的命令如下。 #date -s 11/13/09 将系统时间设定成下午1点12分0秒的命令如下。#date -s 13:12:00 ---- 注意&#xff0c;这里说的是系统时间&#xff0c;是linux由操作系统维护的。 ---- 在系统…

Linux 输入输出重定向 2>/dev/null和>/dev/null 2>1和2>1>/dev/nul

From&#xff1a;https://www.cnblogs.com/520playboy/p/6275022.html 2>/dev/null 和 >/dev/null 2>&1 和 2>&1>/dev/null &#xff1a;https://blog.csdn.net/zhongqi2513/article/details/78613768 连接远程机器执行 shell 命令的一个使用示例&…

c语言向指定文件写入程序,C语言同时向不同的文件写入不同的数据

C语言同时向不同的文件写入不同的数据这个我写了好久才写出来的&#xff0c;之前不知道是什么原因总是不能同时一起写&#xff0c;而且写完一个程序就死了&#xff0c;后来在网上查到一篇文章 http://blog.csdn.net/feixiaoxing/article/details/7237649通过修改变成以下代码。…

Effective Java~44. 坚持使用标准的函数接口

在 java.util.Function 中有 43 个接口。不能指望全部记住它们&#xff0c;但是如果记住了六个基本接口&#xff0c;就可以在需要它们时派生出其余的接口。基本接口操作于对象引用类型。 Operator 接口表示方法的结果和参数类型相同。 Predicate 接口表示其方法接受一个参数并…

SQL Server 执行 字符串

EXEC (字符串或变量) 例&#xff1a; EXEC (SELECT * FROM Orders) 或 DECLARE sql nvarchar(50)SET sqlSELECT * FROM OrdersEXEC (sql)转载于:https://www.cnblogs.com/duwx/archive/2009/11/19/1606152.html

Python爬取大量数据时防止被封IP

From&#xff1a;http://blog.51cto.com/7200087/2070320 基于scrapy框架的爬虫代理IP设置&#xff1a;https://www.jianshu.com/p/074c36a7948c Scrapy: 针对特定响应状态码&#xff0c;使用代理重新请求&#xff1a;http://www.cnblogs.com/my8100/p/scrapy_middleware_aut…