Chapter 6 Lambda Cookbook
6.1: Develop the code that use Java SE 8 collection improvements: Collection.removeIf, List.replaceAll, Map.computeIfAbsent/Present, Map.forEach
Java 8 Changes
java.util.Collection<E>
Interface changes
default boolean removeIf(Predicate<? super E> filter)
- Removes all of the elements of this collection that satisfy the given predicate.
default Stream<E> stream()
- Returns a sequential Stream with this collection as its source.
default Stream<E> parallelStream()
- Returns a possibly parallel Stream with this collection as its source.
It is allowable for this method to return a sequential stream.
java.util.List<E>
Interface changes
default void replaceAll(UnaryOperator<E> operator)
- Replaces each element of this list with the result of applying the operator to that element.
it mutates the elements of the List.
default void sort(Comparator<? super E> c)
- Sorts this list according to the order induced by the specified Comparator.
If the specified comparator is null then all elements in this list will be sorted by
natural order, elems must implement the Comparable interface
java.util.Iterator<E>
Interface changes
default void forEachRemaining(Consumer<? super E> action)
- Performs the given action for each remaining element until all elements have been processed
java,util.Comparator Interface changes
default Comparator<T> reversed()
- Returns a comparator that imposes the reverse ordering of this comparator.
java.util.Map
default void forEach(BiConsumer<? super K,? super V> action)
- Performs the given action for each entry in this map
default void replaceAll(BiFunction<? super K,? super V,? extends V> function)
- Replaces each entry's value with the result of invoking the given function on that entry
default V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
- If there is no value for the key, then it computes its value using the given mapping function
and inserts it if the value!=null
default V computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)
- If the value for the specified key is present and non-null, attempts to compute a new mapping
given the key and its current mapped value.
If the function returns null, the mapping is removed.
default V compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)
- Computes a mapping for the specified key and its current mapped value
Section 6.2 is soon after Section 6.3:
6.3: Use merge, flatMap methods on a collection
java.util.Map<K, V>
default V merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction)
- If there is no value for this key, use value, if there is, pass to func and assign that
value to the key. If new value is null, removes the key from map
e.g. To either create or append a String msg to a value mapping:
map.merge(key, msg, String::concat)
java.util.stream.Stream
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
- Returns a stream consisting of the results of replacing each element of this stream with the
contents of a mapped stream
Example:
.flatMap(e -> Stream.of(e.split(" ")))
-> Returns a stream of R
instead of just R
1
2
3
4
5
6
7
8
9
List<String> list = Arrays.asList("Zello Some", "New Some", "Thing New", "zGood");
List<String> list2 = list.stream()
.flatMap(e -> Stream.of(e.split(" ")))
.peek(s -> System.out.println(s + " "))
.distinct()
.sorted()
.collect(Collectors.toList());
System.out.println("Unique words = " + list2);
Output
Zello
Some
New
Some
Thing
New
zGood
Unique words = [New, Some, Thing, Zello, zGood]
Note the difference with map method
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
- Both map and flatMap take in a Function <T, R>
- flatMap R -> Stream<? extends R> whereas map R -> R
- flatMap is useful when you want to split the incoming stream elements into another stream of same type.
6.2 Read files using lambda improvements: Files.find, lines(), walk()
Streams have a BaseStream.close()
method and implement AutoCloseable
, but nearly all stream instances do not actually need to be closed after use.
Generally, only streams whose source is an IO channel (such as those returned by Files.lines(Path, Charset))
will require closing
Most streams are backed by collections, arrays, or generating functions, require no special closing.
The below methods opens up some of other file resource and should be used with the try-with-resources to ensure that the stream’s close method is invoked.
public static Stream<Path> list(Path dir) throws IOException
- Return a lazily populated Stream, the elements of which are the entries in the directory.
The listing is not recursive.
walk:
public static Stream<Path> walk(Path start,
int maxDepth,
FileVisitOption... options) throws IOException
public static Stream<Path> walk(Path start,
FileVisitOption... options) throws IOException
- Return a Stream that is lazily populated with Path by walking the file tree rooted at a given
starting file. The file tree is traversed depth-first, the elements in the stream are Path
objects that are obtained as if by resolving the relative path against start.
find:
public static Stream<Path> find(Path start,
int maxDepth,
BiPredicate<Path,BasicFileAttributes> matcher,
FileVisitOption... options) throws IOException
- Return a Stream that is lazily populated with Path by searching for files in a file tree
rooted at a given starting file.
lines
public static Stream<String> lines(Path path, Charset cs) throws IOException
public static Stream<String> lines(Path path) throws IOException -> Uses UTF-8 charset
- Read all lines from a file as a Stream. Unlike readAllLines, this method does not read
all lines into a List, but instead populates lazily as the stream is consumed.
The returned stream encapsulates a Reader so this should be called with try-with-resources.
6.4: Describe other stream sources: Arrays.stream(), IntStream.range()
Arrays:
public static <T> Stream<T> stream(T[] array)
public static <T> Stream<T> stream(T[] array, int startInclusive, int endExclusive)
- Returns a sequential Stream with the specified array as its source.
public static IntStream stream(int[] array)
- Returns a sequential IntStream with the specified array as its source.
public static LongStream stream(long[] array)
- Returns a sequential LongStream with the specified array as its source.
public static DoubleStream stream(double[] array)
- Returns a sequential DoubleStream with the specified array as its source
Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
String[] strArray = {"A", "B", "PC", "D", "PM"};
Arrays.stream(strArray)
.filter(s -> s.startsWith("P"))
.forEach(System.out::println);
long[] longArr = {1L, 2L, 3L, 5L, 10L};
LongStream longStream = Arrays.stream(longArr);
System.out.println("Sum = " + longStream.sum());
Output:
PC
PM
Sum = 21
IntStream:
static IntStream range(int startInclusive, int endExclusive)
- Returns range from start to end-1
static IntStream rangeClosed(int startInclusive, int endInclusive)
- Returns range from start to end - Both inclusive
Stream<Integer> boxed()
- Returns a Stream consisting of the elements of this stream, each boxed to an Integer.
Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
IntStream intStream = IntStream.range(1, 20);
intStream.forEach(i -> System.out.print(i + " "));
System.out.println("\nAverage: " + IntStream.range(1, 20).average());
// Note it includes numbers upto 20
IntStream intStream2 = IntStream.rangeClosed(1, 20);
intStream2.forEach(i -> System.out.print(i + " "));
Output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Average: OptionalDouble[10.0]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
IntSummaryStatistics (not mentioned for exam)
A state object for collecting statistics such as count, min, max, sum, and average.
IntSummaryStatistics stats = people.stream()
.collect(Collectors.summarizingInt(Person::getDependents));
Next Chapter 7. Method Enhancements