// Prints all large anagram groups in a dictionary iteratively publicclassAnagrams { publicstaticvoidmain(String[] args)throws IOException { Filedictionary=newFile(args[0]); intminGroupSize= Integer.parseInt(args[1]); Map<String, Set<String>> groups = newHashMap<>(); try (Scanners=newScanner(dictionary)) { while (s.hasNext()) { Stringword= s.next(); groups.computeIfAbsent(alphabetize(word), (unused) -> newTreeSet<>()).add(word); } }
for (Set<String> group : groups.values()) if (group.size() >= minGroupSize) System.out.println(group.size() + ": " + group); }
try (Stream<String> words = Files.lines(dictionary)) { words.collect(groupingBy(word -> alphabetize(word))) .values().stream() .filter(group -> group.size() >= minGroupSize) .forEach(g -> System.out.println(g.size() + ": " + g)); } } // alphabetize method is the same as in original version }
// Two possible declarations for the swap method publicstatic <E> voidswap(List<E> list, int i, int j); publicstaticvoidswap(List<?> list, int i, int j);
这两个声明中的哪一个更可取,为什么? 在公共 API 中,第二个更好,因为它更简单。 你传入一个列表(任何列表),该方法交换索引的元素。 没有类型参数需要担心。 通常, 如果类型参数在方法声明中只出现一次,请将其替换为通配符。 如果它是一个无限制的类型参数,请将其替换为无限制的通配符; 如果它是一个限定类型参数,则用限定通配符替换它。
第二个 swap 方法声明有一个问题。 这个简单的实现不会编译:
1 2 3
publicstaticvoidswap(List<?> list, int i, int j) { list.set(i, list.set(j, list.get(i))); }
试图编译它会产生这个不太有用的错误信息:
1 2 3 4 5 6
Swap.java:5: error: incompatible types: Object cannot be converted to CAP#1 list.set(i, list.set(j, list.get(i))); ^ where CAP#1 is a fresh type-variable: CAP#1extendsObject from capture of ?
// Enum type with data and behavior publicenumPlanet { MERCURY(3.302e+23, 2.439e6), VENUS (4.869e+24, 6.052e6), EARTH (5.975e+24, 6.378e6), MARS (6.419e+23, 3.393e6), JUPITER(1.899e+27, 7.149e7), SATURN (5.685e+26, 6.027e7), URANUS (8.683e+25, 2.556e7), NEPTUNE(1.024e+26, 2.477e7);
privatefinaldouble mass; // In kilograms privatefinaldouble radius; // In meters privatefinaldouble surfaceGravity; // In m / s^2 // Universal gravitational constant in m^3 / kg s^2 privatestaticfinaldoubleG=6.67300E-11;
Weight on MERCURY is 69.912739 Weight on VENUS is 167.434436 Weight on EARTH is 185.000000 Weight on MARS is 70.226739 Weight on JUPITER is 467.990696 Weight on SATURN is 197.120111 Weight on URANUS is 167.398264 Weight on NEPTUNE is 210.208751
// Enum type that switches on its own value - questionable publicenumOperation { PLUS, MINUS, TIMES, DIVIDE;
// Do the arithmetic operation represented by this constant publicdoubleapply(double x, double y) { switch(this) { case PLUS: return x + y; case MINUS: return x - y; case TIMES: return x * y; case DIVIDE: return x / y; } thrownewAssertionError("Unknown op: " + this); } }
// Enum type with constant-specific method implementations publicenumOperation { PLUS {publicdoubleapply(double x, double y){return x + y;}}, MINUS {publicdoubleapply(double x, double y){return x - y;}}, TIMES {publicdoubleapply(double x, double y){return x * y;}}, DIVIDE{publicdoubleapply(double x, double y){return x / y;}};
// Implementing a fromString method on an enum type privatestaticfinal Map<String, Operation> stringToEnum = Stream.of(values()).collect( toMap(Object::toString, e -> e));
// Returns Operation for string, if any publicstatic Optional<Operation> fromString(String symbol) { return Optional.ofNullable(stringToEnum.get(symbol)); }
@Override publicbooleanequals(Object o) { if (o == null || o.getClass() != getClass()) returnfalse; Pointp= (Point) o; return p.x == x && p.y == y; }
只有当对象具有相同的实现类时,才会产生相同的效果。这看起来可能不是那么糟糕,但是结果是不可接受的:一个 Point 类子类的实例仍然是一个 Point 的实例,它仍然需要作为一个 Point 来运行,但是如果你采用这个方法,就会失败!假设我们要写一个方法来判断一个 Point 对象是否在 unitCircle 集合中。我们可以这样做: