使用 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