Effective Java, 3rd Edition Chapter 7: Lambdas and Streams Items 42-48 Last modified Fall 2018 Paul Ammann
More Item 42: Prefer lambdas to anonymous classes Old Java: interfaces with one method represented function types: // Anonymous class instance as function object - obsolete! Collections.sort(words, new Comparator<String>() { public int compare(String s1, String s2) { return Integer.compare(s1.length(), s2.length()); } }); In Java 8, use lambdas to instantiate small function objects: // Lambda expression as function object (replaces anonymous class) Collections.sort(words, (s1, s2) -> Integer.compare(s1.length(), s2.length())); With Comparator construction method: Collections.sort(words, comparingInt(String::length)); With new sort method added to List interface: words.sort(comparingInt(String::length));
More Item 42 A more complex enum example: old version // Enum type with constant-specific class bodies & data (Item 34) public enum Operation { PLUS("+") { public double apply(double x, double y) { return x + y; } }, MINUS("-") { public double apply(double x, double y) { return x - y; } }, TIMES("*") { public double apply(double x, double y) { return x * y; } }, DIVIDE("/") { public double apply(double x, double y) { return x / y; } }; private final String symbol; Operation(String symbol) { this.symbol = symbol; } @Override public String toString() { return symbol; } public abstract double apply(double x, double y); }
More Item 42 A more complex enum example: updated version // Enum with function object fields & constant-specific behavior public enum Operation { PLUS ("+", (x, y) -> x + y), MINUS ("-", (x, y) -> x - y), TIMES ("*", (x, y) -> x * y), DIVIDE("/", (x, y) -> x / y); private final String symbol; private final DoubleBinaryOperator op; // lambda instance field! Operation(String symbol, DoubleBinaryOperator op) { this.symbol = symbol; this.op = op; } @Override public String toString() { return symbol; } public double apply(double x, double y) { return op.applyAsDouble(x, y);
More Item 42 Anonymous classes still have their uses Downside for lambdas in constant-specific method bodies? They lack names and documentation, so keep them short! Sometimes a constant-specific method body is more readable Anonymous classes still have their uses Instantiating abstract classes Instantiating interfaces with multiple methods lambdas can’t references themselves
Item 43: Prefer method references to lambdas Where method references are shorter and clearer, use them; where they aren’t, stick with lambdas map.merge(key, 1, (count, incr) -> count + incr) vs. map.merge(key, 1, Integer::sum) Note that the merge() method in Map has the following documentation. What does that tell us about the example? default V merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction) If the specified key is not already associated with a value or is associated with null, associates it with the given non-null value.
More Item 43 Java’s 5 kinds of method references Method Ref Type Example Lambda Equivalent Static Integer::parseInt str -> Integer.parseInt(str) Bound Instant.now()::isAfter Instant then = Instant.now(); t -> then.isAfter(t) Unbound String::toLowerCase str -> str.toLowerCase() Class Constructor TreeMap<K,V>::new () -> new TreeMap<K,V> Array Constructor int[]::new len -> new int[len]
Item 44: Favor the use of standard functional interfaces java.util.function has 43 predefined functional interfaces Use them! Usually better not to rewrite, but there are exceptions.
More Item 44 Java’s standard functional interfaces: variants on the 6 types below Interface Function Signature Example UnaryOperator<T> T apply(T t) String::toLowerCase BinaryOperator<T> T apply(T t1, T t2) BigInteger::add Predicate<T> boolean test(T t) Collection::isEmpty Function<T,R> R apply(T t) Arrays::asList Supplier<T> T get() Instant::now Consumer<T> void accept(T t) System.out::println
Item 45: Use streams judiciously Stuff
Item 46: Prefer side-effect-free functions in streams Stuff
Item 47: Prefer Collection to Stream as a return type Stuff
Item 48: Use caution when making streams parallel Stuff