import java.util.Arrays;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors; public class Herb {
public enum Type {
ANNUAL, PERENNTAL, BIENNIAL
} private final String name;
private final Type type; Herb(String name, Type type) {
this.name = name;
this.type = type;
} @Override
public String toString() {
return name;
} public static void main(String[] args) {
// 将集合放到一个按照类型的序数进行索引的数组中来实现 替换
Herb[] garden = { new Herb("一年生1", Type.ANNUAL), new Herb("一年生2", Type.ANNUAL), new Herb("两年生1", Type.BIENNIAL),
new Herb("两年生2", Type.BIENNIAL), new Herb("多年生1", Type.PERENNTAL), new Herb("多年生2", Type.PERENNTAL) }; // @SuppressWarnings("unchecked")//产生泛型数组,且手工操作索引
// Set<Herb>[] herbsByType = (Set<Herb>[]) new Set[Herb.Type.values().length];
// for (int i = 0; i < herbsByType.length; i++) {
// herbsByType[i] = new HashSet<Herb>();
// }
// for (Herb h : garden) {
// herbsByType[h.type.ordinal()].add(h);
// //System.out.println(h.type);
// }
// for (int i = 0; i < herbsByType.length; i++) {
// System.out.printf("%s: %s%n", Herb.Type.values(), herbsByType[i]);
// } Map<Herb.Type, Set<Herb>> herbsByType = new EnumMap<Herb.Type, Set<Herb>>(Herb.Type.class);
for (Herb.Type t : Herb.Type.values()) {
herbsByType.put(t, new HashSet<Herb>());
}
for (Herb h : garden) {
herbsByType.get(h.type).add(h);
}
System.out.println(herbsByType); //如果采用的是stream
long startTime = System.currentTimeMillis();
// 这段代码的问题在于,它选择了自己的 map 实现,而实际上它不是 EnumMap,所以它不会将版本的空间和时间性能与显式 EnumMap 匹配。
System.out.println(Arrays.stream(garden).collect(Collectors.groupingBy(p -> p.type)));
long endTime = System.currentTimeMillis();
System.out.println("程序运行时间:" + (endTime - startTime) + "ms");
结果:{PERENNTAL=[多年生1, 多年生2], ANNUAL=[一年生1, 一年生2], BIENNIAL=[两年生1, 两年生2]}
程序运行时间:45ms
// 要纠正这个问题,可以使用 Collectors.groupingBy 的三参数形式,它允许调用者使用 mapFactory 参数指定 Map 实现:
long startTime2 = System.currentTimeMillis();
System.out.println(Arrays.stream(garden)
.collect(Collectors.groupingBy(p -> p.type, () -> new EnumMap<>(Type.class), Collectors.toSet())));
long endTime2 = System.currentTimeMillis();
System.out.println("程序运行时间:" + (endTime2 - startTime2) + "ms");
}
}
结果: {ANNUAL=[一年生2, 一年生1], PERENNTAL=[多年生1, 多年生2], BIENNIAL=[两年生2, 两年生1]}
程序运行时间:1ms

使用 ENUMMAP 替代序数索引的更多相关文章

  1. Effective Java 第三版——37. 使用EnumMap替代序数索引

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  2. 用EnumMap代替序数索引

    用EnumMap代替序数索引   有时候,会见到利用ordinal方法来索引数组的代码.例如下面这个简化的类,表示一种烹饪用的香草: public class Herb { public enum T ...

  3. 【Effective Java】9、使用EnumMap代替序数索引

    package cn.xf.cp.ch02.item33; import java.util.EnumMap; import java.util.HashSet; import java.util.M ...

  4. 第33条:用EnumMap代替序数索引

    有时候,会见到利用ordinal方法来索引数组的代码.例如下面这个简化的类,表示一种烹饪用的香草: public class Herb { public enum Type { ANNUAL, PER ...

  5. Effective Java 第三版——35. 使用实例属性替代序数

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  6. effective-java学习笔记---使用实例属性替代序数35

    永远不要从枚举的序号中得出与它相关的值; 请将其保存在实例属性中: public enum Ensemble { SOLO(1), DUET(2), TRIO(3), QUARTET(4), QUIN ...

  7. 《Effective Java 第三版》目录汇总

    经过反复不断的拖延和坚持,所有条目已经翻译完成,供大家分享学习.时间有限,个别地方翻译得比较仓促,希望有疑虑的地方指出批评改正. 第一章简介 忽略 第二章 创建和销毁对象 1. 考虑使用静态工厂方法替 ...

  8. Effective.Java第34-44条(枚举)

    34.  使用枚举类型替代整型常量 常量的语义表达不清晰,只能靠前面的名称来区分.枚举具有可读性.更安全.更强大等优势.而且枚举类型对象之间的值比较可以使用==来比较值是否相等的,不是必须使用equa ...

  9. [Effective Java 读书笔记] 第6章 枚举和注解

    第三十条 用enum代替int 总得来说,使用enum有几点好处 1.编译时的类型安全, 2.可以保证就是自己定义的值,不会有月结风险, 3.每个枚举类型有自己的命名空间 4.枚举可以添加任意的方法和 ...

随机推荐

  1. TamperMonkey 使用指南以及脚本推荐

    写在前面 Chrome浏览器是最适合开发者使用的浏览器,不仅仅是因为Chrome对于Js的友好支持,更是由于Chrome支持丰富且功能强大的插件,扩展了浏览器的功能和使用体验. 在这些插件里面,相信你 ...

  2. python scraping webs - python取得NIPS oral paper列表

    from lxml import html import requests # using xpath # page = requests.get('http://econpy.pythonanywh ...

  3. c#判断字符串是否可以转日期格式

    在C#中,对格式的判断有一类专门函数,那就是TryParse.TryParse在各个不同的类型类(如int,string,DateTime)中,都是存在的.在TryParse中一般有两个参数,一个是待 ...

  4. 深入浅出Mybatis系列三-配置详解之properties与environments(mybatis源码篇)

    注:本文转载自南轲梦 注:博主 Chloneda:个人博客 | 博客园 | Github | Gitee | 知乎 上篇文章<深入浅出Mybatis系列(二)---配置简介(mybatis源码篇 ...

  5. java学习笔记之IO编程—对象序列化

    对象序列化就是将内存中保存的对象以二进制数据流的形式进行处理,可以实现对象的保存或网络传输. 并不是所有的对象都可以被序列化,如果要序列化的对象,那么对象所在的类一定要实现java.io.Serial ...

  6. 自定义Redux

    实现mini版redux 1. 理解redux模块 1). redux模块整体是一个对象模块 2). 内部包含几个函数 createStore(reducers) // reducers: funct ...

  7. php 对象、json 、XML、数组互转

    对象转json $json=json_encode($postObj,JSON_FORCE_OBJECT); json转对象 $obj=json_encode($json); json转数组 $arr ...

  8. DBeaver下载驱动文件失败

    今天首次使用DBeaver软件链接数据库时会进行下载驱动文件,例如如下图所示: 在上图中显示了下载驱动文件失败,提示“无法解决库文件,请检查网络设置”.其实,是可以正常上网的,可能是公司内网的限制,或 ...

  9. 服务&软件&基础设施的区别

    IT基础设施: 软件 硬件 数据库相关DBM 网络相关 networking(网络通信) 以上4个会出现的比较多 application people 上面的东西都能提供IT服务 一半的互联网公司都会 ...

  10. chrome json接口数据 插件

    chrome json接口数据 插件 JSON-Handle 官网 下载后 地址栏输入 chrome://extensions/ 将下载的文件拖入页面 OK