《Effective Java 第三版》——第二章 创建和销毁对象
《Effective Java 第三版》——第三章 所有对象都通用的方法
《Effective Java 第三版》——第四章 类和接口
《Effective Java 第三版》——第六章 枚举和注解
enum 说的是一类问题,明白原理会运用代码就行
package effectivejava.chapter6.item37; import java.util.*; import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.toSet; // Using an EnumMap to associate data with an enum (Pages 171-3) // Simplistic class representing a plant (Page 171) 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; } public static void main(String[] args) { Plant[] garden = { new Plant("Basil", LifeCycle.ANNUAL), new Plant("Carroway", LifeCycle.BIENNIAL), new Plant("Dill", LifeCycle.ANNUAL), new Plant("Lavendar", LifeCycle.PERENNIAL), new Plant("Parsley", LifeCycle.BIENNIAL), new Plant("Rosemary", LifeCycle.PERENNIAL) }; // Using ordinal() to index into an array - DON'T DO THIS! (Page 171) Set<Plant>[] plantsByLifeCycleArr = (Set<Plant>[]) new Set[Plant.LifeCycle.values().length]; for (int i = 0; i < plantsByLifeCycleArr.length; i++) plantsByLifeCycleArr[i] = new HashSet<>(); for (Plant p : garden) plantsByLifeCycleArr[p.lifeCycle.ordinal()].add(p); // Print the results for (int i = 0; i < plantsByLifeCycleArr.length; i++) { System.out.printf("%s: %s%n", Plant.LifeCycle.values()[i], plantsByLifeCycleArr[i]); } // Using an EnumMap to associate data with an enum (Page 172) 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); // Naive stream-based approach - unlikely to produce an EnumMap! (Page 172) System.out.println(Arrays.stream(garden) .collect(groupingBy(p -> p.lifeCycle))); // Using a stream and an EnumMap to associate data with an enum (Page 173) System.out.println(Arrays.stream(garden) .collect(groupingBy(p -> p.lifeCycle, () -> new EnumMap<>(LifeCycle.class), toSet()))); } }
/Library/Java/JavaVirtualMachines/jdk-13.0.2.jdk/Contents/Home/bin/java -Dfile.encoding=UTF-8 -classpath /Users/didi/git/effective-java-3e-source-code/bin effectivejava.chapter6.item37.Plant ANNUAL: [Basil, Dill] PERENNIAL: [Rosemary, Lavendar] BIENNIAL: [Carroway, Parsley] {ANNUAL=[Basil, Dill], PERENNIAL=[Rosemary, Lavendar], BIENNIAL=[Carroway, Parsley]} {BIENNIAL=[Carroway, Parsley], ANNUAL=[Basil, Dill], PERENNIAL=[Lavendar, Rosemary]} {ANNUAL=[Basil, Dill], PERENNIAL=[Rosemary, Lavendar], BIENNIAL=[Carroway, Parsley]} Process finished with exit code 0
package effectivejava.chapter6.item37; import java.util.*; import java.util.stream.Stream; import static java.util.stream.Collectors.*; // Using a nested EnumMap to associate data with enum pairs - (Pages 174-5) public enum Phase { SOLID, LIQUID, GAS; public enum Transition { MELT(SOLID, LIQUID), FREEZE(LIQUID, SOLID), BOIL(LIQUID, GAS), CONDENSE(GAS, LIQUID), SUBLIME(SOLID, GAS), DEPOSIT(GAS, SOLID); // // Adding a new phase (Page 175) // SOLID, LIQUID, GAS, PLASMA; // public enum Transition { // MELT(SOLID, LIQUID), FREEZE(LIQUID, SOLID), // BOIL(LIQUID, GAS), CONDENSE(GAS, LIQUID), // SUBLIME(SOLID, GAS), DEPOSIT(GAS, SOLID), // IONIZE(GAS, PLASMA), DEIONIZE(PLASMA, GAS); private final Phase from; private final Phase to; Transition(Phase from, Phase to) { this.from = from; this.to = to; } // Initialize the phase transition map private static final Map<Phase, Map<Phase, Transition>> m = Stream.of(values()).collect(groupingBy(t -> t.from, () -> new EnumMap<>(Phase.class), toMap(t -> t.to, t -> t, (x, y) -> y, () -> new EnumMap<>(Phase.class)))); public static Transition from(Phase from, Phase to) { return m.get(from).get(to); } } // Simple demo program - prints a sloppy table public static void main(String[] args) { for (Phase src : Phase.values()) { for (Phase dst : Phase.values()) { Transition transition = Transition.from(src, dst); if (transition != null) System.out.printf("%s to %s : %s %n", src, dst, transition); } } } }
// Initialize the phase transition map private static final Map<Phase, Map<Phase, Transition>> m = Stream.of(values()).collect(groupingBy(t -> t.from, () -> new EnumMap<>(Phase.class), toMap(t -> t.to, t -> t, (x, y) -> y, () -> new EnumMap<>(Phase.class))));
Stream 这段代码有点绕
挺精巧的:用接口模拟可扩展的枚举
第39条把代码跑一遍就清楚了