Learning to Love the Lambda in the Stream
Introduction to Java Lambda expressions
- What is a Lambda?
- Functional Interfaces (FI) in Java 8
- Assigning a Lambda to a FI.
- Compare a Lambda to an anonymous inner class
The Built In Java FIs
- Comparable, Comparator - Segway back to definition of FIs, that pre Java 8 interfaces are FIs if they have exactly 1 abstract method.
Our First Stream: Add Integer Elements in a Collection
- Show adding example using a traditional imperative programming loop
- Show adding example using a Stream.
- Show adding example using parallel stream. Since addition is commutative and associative, it is ideal for parallel processing
- Show adding example using fork / join. Not nearly as nice as using the stream
- This operation is a reduction, because it creates one value based processing the stream elements
New requirement: Skip numbers divisible by 4
- Review the predicate interface
- Define the stream using Stream.of instead of collection
- Create a predicate lambda for numbers not divisible by 4
- Use the filter operation on the stream with the predicate.
- Use Stream.forEach(System.out::println) to check list.
- Example of a method reference bound to a Consumer interface.
- Review Consumer interface.
- Compute the sum without the numbers divisible by 4
- Get the sum, average, min, max, and count using statistics.
Get sum of numbers divisible by 4, and of numbers not divisible by 4
- Introduce partitions
- Define stream using IntStream.rangeClosed
- Use predicate lambda to create the partitions using partitioningBy collector.
- Use a collector on the partition to sum the elements (reduce each partition)
Get sum of N modulo 4
- Introduce Grouping
- Partitioning is special case of grouping
- Use function lambda to take modulus of 4 for map key
- Use groupingBy to group the map with N % 4 as the keys.
- Show map with values for keys 0..3.
- Use a collection on the grouping to sum the elements (reduce each grouping)
- Reductions, such as a sum will run forever.
- Introduce findFirst, findAny, allMatch, anyMatch, noneMatch predicate operations.
- findFirst and findAny will always terminate.
- Termination of allMatch, anyMatch, and noneMatch depend on the underlying data.
- Use the limit operation to convert an infinite stream into a finite stream.
- Use skip to skip element processing.
- When used on an infinite stream, the result is an infinite stream with the specified number of elements skipped.
- When used on a finite stream, the elements have those elements skipped, with correspondingly fewer elements remaining for processing.
- A skip operation that precedes a limit operation will have no effect on how many elements are processed by the stream resulting from the limit operation
- A skip operation that succeeds a limit operation will reduce the number of elements to be processed by the number specified in the skip operation
- Use the supplier FI to produce and process an infinite stream of random numbers
Review Builder design pattern
Show how the builder design pattern can be used to insert support unit tests.
- Unit Test supplies a builder that appends the peek intermediate operation to the stream. The peek operation may be used observe and test the data from the stream.
- Production code uses a default identity builder, that is a builder that returns the stream it is given without adding any operations to it.
Java 8 lambdas and streams introduce a powerful new framework into the java language. This framework allows complex and possibly parallel computations to be expressed succinctly and performed efficiently. Streams are a complement to Object Oriented Programming: OO Programming has traditionally allowed us to override operations in subclasses but keep control structures in suberclasses. Streams allow the control structures themselves to be abstracted away, allowing the developer to focus on the problem at hand and leaving the details to the stream framework. The builder pattern may be used to support unit testing of streams. Lambdas and streams provide a way to learn and experiment with functional programming concepts without the daunting task of also learning a new programming language. Frequent use of lambdas will make learning a functional programming language and ecosystem an easier task, because the functional programming concepts will have familiarity.
The contents of the Notes for Reviewers and Prerequisites disappear every time I save them so I am writing them here.
Notes for Reviewers
The presentation and example code will be placed in GitHub prior to the presentation. The example code will be well documented to illustrate each point during the presentation. It will be run at the corresponding point in the presentation to show that the lambdas and streams work as advertised.
Basic knowledge of Java Programming: loops and Collection. Functional programming is not a prerequisite.