使用 ENUMMAP 替代序数索引

Posted wcss

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用 ENUMMAP 替代序数索引相关的知识,希望对你有一定的参考价值。

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 替代序数索引的主要内容,如果未能解决你的问题,请参考以下文章

Effective Java 读书笔记之五 枚举和注解

一文看懂EnumMap

inline内联函数

EnumMap 源码分析

替代拉链的替代方式

java集合Map集合之EnumMap详解