Chapter 1. Java 8, 9, 10, and 11: what’s happening?
Figure 1.1. Programming-language ecosystem and climate change
Figure 1.2. Unix commands operating on streams
Figure 1.3. Passing method compareUsingCustomerId as an argument to sort
Figure 1.4. Passing the method reference File::isHidden to the method listFiles
Figure 1.6. Forking filter onto two CPUs and joining the result
Chapter 2. Passing code with behavior parameterization
Figure 2.1. Different strategies for selecting an Apple
Figure 2.2. Parameterizing the behavior of filterApples and passing different filter strategies
Figure 2.3. Parameterizing the behavior of filterApples and passing different filter strategies
Figure 2.4. Behavior parameterization versus value parameterization
Chapter 3. Lambda expressions
Figure 3.1. A lambda expression is composed of parameters, an arrow, and a body.
Figure 3.2. Tasks A and B are surrounded by boilerplate code responsible for preparation/cleanup.
Figure 3.3. Four-step process to apply the execute-around pattern
Figure 3.4. Deconstructing the type-checking process of a lambda expression
Figure 3.6. Using andThen versus compose
Figure 3.7. A transformation pipeline using andThen
Figure 3.8. Area under the function f(x) = x + 10 for x from 3 to 7
Chapter 4. Introducing streams
Figure 4.1. Chaining stream operations forming a stream pipeline
Figure 4.2. Filtering a menu using a stream to find out three high-calorie dish names
Figure 4.3. Streams versus collections
Chapter 5. Working with streams
Figure 5.1. Filtering a stream with a predicate
Figure 5.2. Filtering unique elements in a stream
Figure 5.3. Truncating a stream
Figure 5.4. Skipping elements in a stream
Figure 5.5. Incorrect use of map to find unique characters from a list of words
Figure 5.6. Using flatMap to find the unique characters from a list of words
Figure 5.7. Using reduce to sum the numbers in a stream
Chapter 6. Collecting data with streams
Figure 6.1. The reduction process grouping the transactions by currency
Figure 6.2. The aggregation process of the summingInt collector
Figure 6.3. The reduction process calculating the total number of calories in the menu
Figure 6.4. Classification of an item in the stream during the grouping process
Figure 6.5. Equivalence between n-level nested map and n-dimensional classification table
Figure 6.6. Combining the effect of multiple collectors by nesting one inside the other
Figure 6.7. Logical steps of the sequential reduction process
Figure 6.8. Parallelizing the reduction process using the combiner method
Chapter 7. Parallel data processing and performance
Figure 7.1. A parallel reduction operation
Figure 7.2. iterate is inherently sequential.
Figure 7.3. The fork/join process
Figure 7.4. The fork/join algorithm
Figure 7.5. The work-stealing algorithm used by the fork/join framework
Figure 7.6. The recursive splitting process
Figure 7.7. The state transitions of the WordCounter when a new Character c is traversed
Chapter 9. Refactoring, testing, and debugging
Figure 9.1. The strategy design pattern
Figure 9.2. The observer design pattern
Figure 9.3. The chain of responsibility design pattern
Figure 9.4. Examining values flowing in a stream pipeline with peek
Chapter 11. Using Optional as a better alternative to null
Figure 11.2. Comparing the map methods of Streams and Optionals
Figure 11.3. A two-level optional
Figure 11.4. Comparing the flatMap methods of Stream and Optional
Figure 11.5. The Person/Car/Insurance dereferencing chain using optionals
Chapter 12. New Date and Time API
Chapter 13. Default methods
Figure 13.1. Adding a method to an interface
Figure 13.3. Single inheritance versus multiple inheritance
Figure 13.4. Multiple behavior composition
Figure 13.5. The most specific default-providing interface wins.
Figure 13.6. Inheriting from a class and implementing two interfaces
Chapter 14. The Java Module System
Figure 14.1. Three separate concerns with dependencies
Figure 14.2. Core structure of a Java module descriptor (module-info.java)
Chapter 15. Concepts behind CompletableFuture and reactive programming
Figure 15.1. A typical mashup application
Figure 15.2. Concurrency versus parallelism
Figure 15.3. Sleeping tasks reduce the throughput of thread pools.
Figure 15.5. Relaxed fork/join
Figure 15.6. An asynchronous method
Figure 15.7. A simple box-and-channel diagram
Figure 15.8. Timing diagram showing three computations: f(x), g(x) and adding their results
Chapter 16. CompletableFuture: composable asynchronous programming
Figure 16.1. Using a Future to execute a long operation asynchronously
Figure 16.2. Why Stream’s laziness causes a sequential computation and how to avoid it
Figure 16.3. Composing synchronous operations and asynchronous tasks
Chapter 17. Reactive programming
Figure 17.1. The key features of a reactive system
Figure 17.3. The life cycle of a reactive application using the Flow API
Figure 17.5. The marble diagrams for the map and merge functions
Chapter 18. Thinking functionally
Figure 18.2. A function with side effects
Figure 18.3. A function with no side effects
Figure 18.4. A function throwing an exception
Figure 18.5. Recursive definition of factorial, which requires several stack frames
Figure 18.6. Tail-recursive definition of factorial, which can reuse a single stack frame
Chapter 19. Functional programming techniques
Figure 19.1. comparing takes a function as parameter and returns another function.
Figure 19.2. The data structure is destructively updated.
Figure 19.3. Functional style with no modifications to the data structure
Figure 19.4. No existing data structure was harmed during the making of this update to Tree.
Chapter 20. Blending OOP and FP: Comparing Java and Scala
Chapter 21. Conclusions and where next for Java
Appendix C. Performing multiple operations in parallel on a stream