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. 【Pyecharts可视化分享】杭州步行热门路线等~

    前言 本文包括内容如下: 杭州步行热门路线 渐变效果散点图 均是Echarts官方提供等示例,本文将会通过Pyecharts来进行实现. 杭州步行热门路线 因为代码中需要调用百度地图,所以开始之前你需 ...

  2. Dell 工作站M4800 安装macOs Mojave

    前言 最近,入手了一台二手Dell工作站M4800,价格为3600,配置如下 个人感觉还是很好用的,配置够用,关键是用料真的足!虽然是16年的机器,但是做工吊打一众游戏本. 然后,重点来了,我安装上了 ...

  3. 【spring】(填坑)sql注入攻击 - 持久层参数化

    结果   填坑失败,并没有看懂是如何检测sql攻击的. 只能说的是: 建议都使用参数化传递sql语句参数.(所以,用hibernate.mybatis等框架的真不用太担心sql攻击问题.) 前言 本文 ...

  4. ASP.NET Core SignalR 使用

    SignalR: 实时 Web 功能使服务器端代码能够即时将内容推送到客户端(包括B/S,C/S,Andriod).   SignalR最新版本为3.0(截止2020-02-28)   SignalR ...

  5. javascript 问题汇总(1)

    1    jquery ajax提交有参数的请求,提示错误“Unsupported Media Type“ 解决:ajax 设置添加  contentType: "application/j ...

  6. vue.js中用npm安装vue-router时报错处理办法

    当在使用npm安装东西的时候,最怕遇到的就是,电脑并不想和你说话,只向你抛出一大堆错误...比如在vue.js中用npm安装vue-router的时候,我就遇到 一脸蒙逼的我默默的念了一句:卧..槽. ...

  7. Mysql快速入门(二)

    多表关联查询 JOIN 按照功能大致分为如下三类: CROSS JOIN(交叉连接) INNER JOIN(内连接或等值连接). OUTER JOIN(外连接) 交叉连接 交叉连接的关键字:CROSS ...

  8. cmdb实现三种方式

    为什么要做CMDB? 1.实现运维自动化,CMDB是实现运维自动化的基石 2.之前做资产统计的时候,使用execl来统计,为了年底资产审计方便 3.运维日常工作繁琐, 4.运行环境不统一 Agent方 ...

  9. Max Sum Plus Plus HDU - 1024 基础dp 二维变一维的过程,有点难想

    /* dp[i][j]=max(dp[i][j-1]+a[j],max(dp[i-1][k])+a[j]) (0<k<j) dp[i][j-1]+a[j]表示的是前j-1分成i组,第j个必 ...

  10. 第一个安卓app——计算器

    几天前,我花了一天时间,结合这段时间所学知识开发出了一个简单的计算器,它由两个TextView和23个Button组成,代码会放在文章结尾. TextView TextView:上面一个TextVie ...