Chapter 1. Java 8, 9, 10, and 11: what’s happening?
1.1. So, what’s the big story?
1.2. Why is Java still changing?
1.2.1. Java’s place in the programming language ecosystem
1.2.3. Passing code to methods with behavior parameterization
1.3.1. Methods and lambdas as first-class citizens
1.5. Default methods and Java modules
Chapter 2. Passing code with behavior parameterization
2.1. Coping with changing requirements
2.1.1. First attempt: filtering green apples
2.1.2. Second attempt: parameterizing the color
2.1.3. Third attempt: filtering with every attribute you can think of
2.2. Behavior parameterization
2.3.2. Fifth attempt: using an anonymous class
2.4.1. Sorting with a Comparator
2.4.2. Executing a block of code with Runnable
3.2. Where and how to use lambdas
3.3. Putting lambdas into practice: the execute-around pattern
3.3.1. Step 1: Remember behavior parameterization
3.3.2. Step 2: Use a functional interface to pass behaviors
3.4. Using functional interfaces
3.5. Type checking, type inference, and restrictions
3.7. Putting lambdas and method references into practice
3.7.2. Step 2: Use an anonymous class
3.8. Useful methods to compose lambda expressions
3.9. Similar ideas from mathematics
2. Functional-style data processing with streams
Chapter 4. Introducing streams
4.2. Getting started with streams
Chapter 5. Working with streams
5.4.1. Checking to see if a predicate matches at least one element
5.6. Putting it all into practice
5.7.1. Primitive stream specializations
5.7.3. Putting numerical streams into practice: Pythagorean triples
Chapter 6. Collecting data with streams
6.5.1. Making sense of the methods declared by Collector interface
6.6. Developing your own collector for better performance
Chapter 7. Parallel data processing and performance
7.1.1. Turning a sequential stream into a parallel one
7.1.2. Measuring stream performance
7.2.1. Working with RecursiveTask
3. Effective programming with streams and lambdas
Chapter 8. Collection API enhancements
8.2. Working with List and Set
8.4. Improved ConcurrentHashMap
Chapter 9. Refactoring, testing, and debugging
9.1. Refactoring for improved readability and flexibility
9.1.1. Improving code readability
9.1.2. From anonymous classes to lambda expressions
9.1.3. From lambda expressions to method references
9.2. Refactoring object-oriented design patterns with lambdas
9.3.1. Testing the behavior of a visible lambda
9.3.2. Focusing on the behavior of the method using a lambda
Chapter 10. Domain-specific languages using lambdas
10.1. A specific language for your domain
10.2. Small DSLs in modern Java APIs
10.2.1. The Stream API seen as a DSL to manipulate collections
10.3. Patterns and techniques to create DSLs in Java
10.3.2. Using nested functions
10.3.3. Function sequencing with lambda expressions
Chapter 11. Using Optional as a better alternative to null
11.1. How do you model the absence of a value?
11.1.1. Reducing NullPointerExceptions with defensive checking
11.1.3. What are the alternatives to null in other languages?
11.2. Introducing the Optional class
11.3. Patterns for adopting Optionals
11.3.1. Creating Optional objects
11.3.2. Extracting and transforming values from Optionals with map
11.3.3. Chaining Optional objects with flatMap
11.3.4. Manipulating a stream of optionals
11.3.5. Default actions and unwrapping an Optional
11.4. Practical examples of using Optional
11.4.1. Wrapping a potentially null value in an Optional
11.4.2. Exceptions vs. Optional
Chapter 12. New Date and Time API
12.1. LocalDate, LocalTime, LocalDateTime, Instant, Duration, and Period
12.1.1. Working with LocalDate and LocalTime
12.1.2. Combining a date and a time
12.2. Manipulating, parsing, and formatting dates
12.3. Working with different time zones and calendars
13.2. Default methods in a nutshell
13.3. Usage patterns for default methods
13.4.1. Three resolution rules to know
13.4.2. Most specific default-providing interface wins
Chapter 14. The Java Module System
14.1. The driving force: reasoning about software
14.2. Why the Java Module System was designed
14.3. Java modules: the big picture
14.4. Developing an application with the Java Module System
14.4.1. Setting up an application
14.5. Working with several modules
14.8. Module declaration and clauses
Chapter 15. Concepts behind CompletableFuture and reactive programming
15.1. Evolving Java support for expressing concurrency
15.1.1. Threads and higher-level abstractions
15.1.2. Executors and thread pools
15.1.3. Other abstractions of threads: non-nested with method calls
15.2. Synchronous and asynchronous APIs
15.2.3. Sleeping (and other blocking operations) considered harmful
15.3. The box-and-channel model
15.4. CompletableFuture and combinators for concurrency
15.5. Publish-subscribe and reactive programming
Chapter 16. CompletableFuture: composable asynchronous programming
16.1.1. Understanding Futures and their limitations
16.1.2. Using CompletableFutures to build an asynchronous application
16.2. Implementing an asynchronous API
16.2.1. Converting a synchronous method into an asynchronous one
16.3. Making your code nonblocking
16.3.1. Parallelizing requests using a parallel Stream
16.3.2. Making asynchronous requests with CompletableFutures
16.4. Pipelining asynchronous tasks
16.4.1. Implementing a discount service
16.4.2. Using the Discount service
16.4.3. Composing synchronous and asynchronous operations
16.4.4. Combining two CompletableFutures: dependent and independent
16.5. Reacting to a CompletableFuture completion
Chapter 17. Reactive programming
17.2. Reactive streams and the Flow API
17.2.1. Introducing the Flow class
17.2.2. Creating your first reactive application
17.2.3. Transforming data with a Processor
17.2.4. Why doesn’t Java provide an implementation of the Flow API?
17.3. Using the reactive library RxJava
6. Functional programming and future Java evolution
Chapter 18. Thinking functionally
18.1. Implementing and maintaining systems
18.2. What’s functional programming?
18.2.2. Referential transparency
Chapter 19. Functional programming techniques
19.2. Persistent data structures
19.2.1. Destructive updates vs. functional
19.3. Lazy evaluation with streams
19.5.1. Caching or memoization
Chapter 20. Blending OOP and FP: Comparing Java and Scala
20.1.2. Basic data structures: List, Set, Map, Tuple, Stream, Option
20.2.1. First-class functions in Scala
Chapter 21. Conclusions and where next for Java
21.1. Review of Java 8 features
21.1.1. Behavior parameterization (lambdas and method references)
21.2. The Java 9 module system
21.3. Java 10 local variable type inference
21.4.1. Declaration-site variance
21.4.3. Richer forms of generics
A. Miscellaneous language updates
B. Miscellaneous library updates
C. Performing multiple operations in parallel on a stream
C.1.1. Implementing the Results interface with the ForkingStreamConsumer
C.1.2. Developing the ForkingStreamConsumer and the BlockingQueueSpliterator