0% found this document useful (0 votes)
12 views545 pages

Modern Java in Action PDF

Modern Java in Action provides essential skills for navigating advancements in Java, focusing on features like lambdas, streams, and the Java Module System. The book emphasizes functional programming concepts to enhance code clarity and maintainability, while also covering practical applications and methodologies for concurrency. Authored by Raoul-Gabriel Urma, it aims to empower developers with insights and best practices for modern Java programming.

Uploaded by

Lại Huân
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views545 pages

Modern Java in Action PDF

Modern Java in Action provides essential skills for navigating advancements in Java, focusing on features like lambdas, streams, and the Java Module System. The book emphasizes functional programming concepts to enhance code clarity and maintainability, while also covering practical applications and methodologies for concurrency. Authored by Raoul-Gabriel Urma, it aims to empower developers with insights and best practices for modern Java programming.

Uploaded by

Lại Huân
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 545

Modern Java in Action PDF

Raoul-Gabriel Urma

Scan to Download
Modern Java in Action
Master Modern Java Features for Innovative
Application Development
Written by Bookey
Check more about Modern Java in Action Summary
Listen Modern Java in Action Audiobook

Scan to Download
About the book
In the ever-evolving landscape of software development,
modern applications leverage innovative designs such as
microservices, reactive architectures, and streaming data.
"Modern Java in Action" equips you with the essential skills to
navigate these advancements by seamlessly connecting the
latest Java features—like lambdas, streams, and the new Java
Module System—with their practical applications. Through
clear examples and meticulous detail, this book prioritizes
your learning experience, enabling you to deepen your
understanding of core Java while mastering contemporary
tools. Discover new methodologies for concurrency and
embrace functional programming concepts that lead to cleaner,
more maintainable code. It’s time to elevate your Java
expertise and tackle modern challenges with confidence!

Scan to Download
About the author
Raoul-Gabriel Urma is a renowned software engineer,
educator, and author with a deep passion for programming and
modern Java technologies. With extensive experience in
software development and a strong background in computer
science, he has contributed significantly to the advancement of
Java through his work in academia and industry. As an expert
in functional programming and the modern features of the Java
ecosystem, Urma has dedicated himself to teaching others how
to leverage these innovations effectively. Through his book
"Modern Java in Action," he aims to empower developers with
practical insights and best practices, making complex concepts
accessible to a wider audience.

Scan to Download
Summary Content List
Chapter 1 : How this book is organized: a roadmap

Chapter 2 : Book forum

Chapter 3 : 1 Java 8, 9, 10, and 11: what?s happening?

Chapter 4 : 2 Passing code with behavior parameterization

Chapter 5 : 3 Lambda expressions

Chapter 6 : 4 Introducing streams

Chapter 7 : 5 Working with streams

Chapter 8 : 6 Collecting data with streams

Chapter 9 : 7 Parallel data processing and performance

Chapter 10 : 8 Collection API enhancements

Chapter 11 : 9 Refactoring, testing, and debugging

Chapter 12 : 10 Domain-specific languages using lambdas

Chapter 13 : 11 Using Optional as a better alternative to null

Chapter 14 : 12 New Date and Time API

Chapter 15 : 13 Default methods

Scan to Download
Chapter 16 : 14 The Java Module System

Chapter 17 : 15 Concepts behind CompletableFuture and

reactive programming

Chapter 18 : 16 CompletableFuture: composable

asynchronous programming

Chapter 19 : 17 Reactive programming

Chapter 20 : 18 Thinking functionally

Chapter 21 : 19 Functional programming techniques

Chapter 22 : 20 Blending OOP and FP: Comparing Java and

Scala

Chapter 23 : 21 Conclusions and where next for Java

Chapter 24 : A.1 Annotations

Chapter 25 : A.2 Generalized target-type inference

Chapter 26 : B.1 Collections

Chapter 27 : B.2 Concurrency

Chapter 28 : B.3 Arrays

Scan to Download
Chapter 29 : B.4 Number and Math

Chapter 30 : B.7 String

Chapter 31 : C.1 Forking a stream

Chapter 32 : D.1 Anonymous classes

Chapter 33 : D.2 Bytecode generation

Chapter 34 : D.3 Invokedynamic to the rescue

Chapter 35 : D.4 Code-generation strategies

Chapter 36 : A

Chapter 37 : C

Chapter 38 : D

Chapter 39 : F

Chapter 40 : I

Chapter 41 : J

Chapter 42 : L

Chapter 43 : N

Chapter 44 : P

Scan to Download
Chapter 45 : R

Chapter 46 : S

Chapter 47 : T

Chapter 48 : Z

Scan to Download
Chapter 1 Summary : How this book is
organized: a roadmap

Section Details

About This Introduces Java 8 and 9 features like lambda expressions, method references, streams, and emphasizes
Book functional programming advantages.

Key Features of
Java 8
Lambda Expressions and Streams: Concise code and functional programming style with efficient
data handling.
Performance Improvements: Optimizes operations with lazy evaluation and parallel processing.

Book Structure

Fundamentals

Chapter 1: Overview of major changes in Java.


Chapter 2: Behavior parameterization significance.
Chapter 3: Lambda expressions and method references.

Functional-Style Data Processing with Streams

Chapter 4: Introduction to streams.


Chapter 5: Stream operations for data processing.
Chapter 6: Using collectors for complex queries.
Chapter 7: Parallel streams usage.

Effective Programming with Streams and Lambdas

Chapter 8: Collection API enhancements.


Chapter 9: Code improvement suggestions using Java 8.
Chapter 10: Designing APIs with domain-specific languages.

Scan to Download
Section Details

Everyday Java

Chapter 11: The Optional class.


Chapter 12: The new Date and Time API.
Chapter 13: Default methods in interfaces.
Chapter 14: Introduction to the Java Module System.

Enhanced Java Concurrency

Chapter 15: Asynchronous APIs and Publish-Subscribe protocol.


Chapter 16: Using CompletableFuture.
Chapter 17: Practical applications of the Java Flow API.

Functional Programming and Future Java Evolution

Chapter 18: Functional programming in Java.


Chapter 19: Advanced functional programming techniques.
Chapter 20: Comparison of Java 8 with Scala features.

Conclusion Readers will understand modern Java programming techniques and best practices for clearer, concise, and
efficient code.

ABOUT THIS BOOK

Modern Java in Action introduces several key concepts and


features introduced in Java 8 and 9, including lambda
expressions, method references, streams, and new APIs
aimed at enhancing programming efficiency and
effectiveness. This book emphasizes the advantages of
functional programming alongside traditional Java
paradigms.

Scan to Download
Key Features of Java 8

-
Lambda Expressions and Streams:
Lambda expressions allow for more concise code, enabling
function parameters and supporting a functional
programming style. Streams provide a new way to handle
collections of data efficiently, allowing for complex queries
similar to SQL without needing to understand databases.

-
Performance Improvements:
Streams optimize operations through lazy evaluation and
parallel processing capabilities, which can lead to more
efficient data handling compared to standard collections.

Book Structure

Modern Java in Action is divided into six parts:


1.
Fundamentals
: Introduces basic concepts like lambda expressions and
behavior parameterization.
- Chapter 1: Overview of major changes in Java.

Scan to Download
- Chapter 2: Behavior parameterization and its significance.
- Chapter 3: In-depth exploration of lambda expressions
and method references.
2.
Functional-Style Data Processing with Streams
: Provides comprehensive coverage of the Streams API.
- Chapter 4: Introduction to streams and their benefits.
- Chapter 5: Stream operations for data processing.
- Chapter 6: Using collectors for complex queries.
- Chapter 7: Parallel streams and their effective usage.
3.
Effective Programming with Streams and Lambdas
: Discusses Java 8 and 9 enhancements and idiomatic
programming practices.
- Chapter 8: Collection API enhancements.
- Chapter 9: Code improvement suggestions using Java 8
features.
- Chapter 10: Designing APIs with domain-specific
languages.
4.
Everyday Java
: Focuses on practical enhancements from Java 8 and 9 for
reliable coding.
- Chapter 11: The Optional class for safer APIs.

Scan to Download
- Chapter 12: The new Date and Time API.
- Chapter 13: Default methods in interfaces.
- Chapter 14: Introduction to the Java Module System.
5.
Enhanced Java Concurrency
: Covers advanced concurrency programming techniques.
- Chapter 15: Asynchronous APIs and the
Publish-Subscribe protocol.
- Chapter 16: Using CompletableFuture for complex
computations.
- Chapter 17: Practical applications of the Java Flow API.
6.
Functional Programming and Future Java
Evolution
: Provides a tutorial on functional programming concepts and
compares Java 8 features with Scala.
- Chapter 18: Introduction to functional programming in
Java.
- Chapter 19: Advanced functional programming
techniques.
- Chapter 20: Comparison of Java 8 with Scala features.
By the end of the book, readers will have developed a
comprehensive understanding of modern Java programming
techniques and best practices, enabling them to write clearer,
more concise, and efficient code.

Scan to Download
Chapter 2 Summary : Book forum

Chapter Overview

In this chapter, we discuss the learning journey with Java 8,


focusing on the transition towards functional-style
programming. We also speculate on future updates and
enhancements expected in Java after version 8, including
anticipated features in Java 9 and minor additions in Java 10.

Appendices

-
Appendix A
: Summarizes minor Java 8 language features not covered in
the main text.

Scan to Download
-
Appendix B
: Provides an overview of key additions to the Java library.
-
Appendix C
: Continues part 2, discussing advanced uses of streams.
-
Appendix D
: Explores the implementation of lambda expressions by the
Java compiler.

Source Code

All source code examples in the book are presented in a


fixed-width font and accompanied by annotations
highlighting key concepts. Source code for all examples is
available on a GitHub repository and can also be downloaded
from the book's website.

Book Forum

Purchasing "Modern Java in Action" grants free access to a


private web forum hosted by Manning Publications. Readers
can comment, ask technical questions, and receive assistance

Scan to Download
from both authors and other users. The forum encourages
meaningful dialogue but does not guarantee specific
responses from the authors.

Links

- Source code:
www.manning.com/books/modern-java-in-action
- Forum:
https://forums.manning.com/forums/modern-java-in-action
- Forum conduct: https://forums.manning.com/forums/about

Scan to Download
Example
Key Point:Embracing functional-style programming
will greatly enhance your Java coding efficiency and
expressiveness.
Example:Imagine you’re working on a complex project;
you decide to refactor the existing code using functional
programming concepts from Java 8, like lambda
expressions and streams. As you replace verbose loops
with concise functional constructs, you realize how
much clearer and more maintainable your code has
become. You'll often find that using these modern
features not only simplifies your logic but also elevates
your programming standards by encouraging
immutability and a declarative approach, ultimately
boosting both productivity and software quality.

Scan to Download
Critical Thinking
Key Point:Transitioning to functional-style
programming with Java 8
Critical Interpretation:The chapter emphasizes the shift
towards functional programming in Java 8 as a major
learning point, which may simplify programming by
promoting immutability and higher-order functions.
However, readers should consider that this viewpoint
could overlook the advantages of traditional
object-oriented programming practices, particularly in
complex systems where mutability and state
management are essential. A critique from sources like
"Java Concurrency in Practice" by Brian Goetz argues
for meticulous threading and state management,
revealing that functional paradigms may introduce their
own complexities and pitfalls that are not considered in
this chapter.

Scan to Download
Chapter 3 Summary : 1 Java 8, 9, 10,
and 11: what?s happening?

3 Java 8, 9, 10, and 11: What’s Happening?

Since the release of Java 1.0 in 1996, Java has gained a


significant following among students, project managers, and
programmers due to its expressiveness and suitability for
various projects. The evolution of Java has been marked by
careful management of new features from Java 1.1 to Java 7,
with Java 8, 9, 10, and 11 introducing noteworthy
advancements.

Key Changes and Their Importance

1.
Java's Continuous Evolution
: The language consistently adapts to meet new computing
needs and challenges, particularly regarding support for
multicore processors and improved programming practices.
2.
Conciseness and Ease of Use in Java 8

Scan to Download
: Java 8 introduced features like the Streams API and lambda
expressions, which allow for more concise and readable
code, making programming easier.
3.
Hardware Considerations
: With the rise of multicore CPUs, previous Java applications
typically utilized only a single core. The introduction of
easier concurrency models in Java 8 helped leverage these
hardware advancements.

Core Features of Java 8 and 9

-
Streams API
: Enables high-level data processing similar to SQL,
improving performance and readability.
-
Method References and Lambdas
: Allow passing functions as arguments, enabling behavior
parameterization and functional-style programming.
-
Install
Default Bookey App to Unlock Full Text and
Methods
Audio
: Facilitate interface evolution without breaking existing
implementations.

Scan to Download
Chapter 4 Summary : 2 Passing code
with behavior parameterization
Section Summary

Introduction User requirements change rapidly; behavior parameterization allows deferring execution of code
blocks for flexible adaptation.

Coping with Enables functions to act on varying instructions without modifying original code; illustrated through
Changing examples like sorting and GUI handling.
Requirements

Improving Filter Explores attempts to filter apples based on criteria with increasing flexibility:
Methods

1. First Attempt Direct check for green apples; lacks adaptability to criteria changes.

2. Second Attempt Parameterizing color improves flexibility but fails to eliminate code repetition.

3. Third Attempt Combines color and weight parameters, leading to complexity and readability issues.

4. Fourth Attempt Introduced `ApplePredicate` interface for encapsulating selection criteria, enhancing flexibility by
following the strategy design pattern.

Tackling Verbosity Noted verbosity in using classes for predicates; anonymous classes are alternatives but still
cumbersome.

5. Lambda Java 8 introduced lambda expressions for cleaner, less verbose code.
Expressions

6. Abstracting Over Filter methods expanded to handle multiple types beyond `Apple`, enhancing general applicability.
List Type

Real-World Examples of behavior parameterization in Java API:


Applications

Sorting with Dynamic sorting criteria can be passed.


Comparator

Executing Code with Represents code executed in threads.


Runnable

Returning Results Models tasks yielding results, improving on Runnable.


with Callable

GUI Event Handling Parameterizes event responses through interfaces.

Conclusion Behavior parameterization enhances adaptability to changing requirements; Java 8 lambdas reduce
verbosity while accepting diverse behaviors for easier code maintenance.

Scan to Download
Summary of Chapter 4: Passing Code with Behavior
Parameterization

Introduction

- User requirements often change rapidly in software


development.
- Behavior parameterization is a pattern that allows flexible
adaptation to these changes by taking blocks of code and
deferring their execution.

Coping with Changing Requirements

- Behavior parameterization enables the implementation of


functions that can later act on varying instructions without
modifying the original code.
- Multiple real-world examples, such as sorting and GUI
event handling, illustrate this concept.

Improving Filter Methods

1.
First Attempt: Filtering Green Apples

Scan to Download
- Initial implementation directly checks for green apples
but doesn't account for changes in criteria.

2.
Second Attempt: Parameterizing Color

- Introduced a parameter for color, improving flexibility


but still repeating code for diverse filters.
3.
Third Attempt: Filtering with Multiple Attributes

- Combined color and weight parameters into a single


method but led to complex and hard-to-read solutions.
4.
Fourth Attempt: Using ApplePredicate Interface

- Introduced an `ApplePredicate` interface to encapsulate


selection criteria, enhancing flexibility and following the
strategy design pattern.
- This approach allowed for cleaner filter methods that
could accept different behaviors.

Tackling Verbosity

Scan to Download
- Noted the verbosity in using classes for simple predicates
and introduced anonymous classes as an alternative.
- However, anonymous classes are still cumbersome and
verbose.
5.
Lambda Expressions

- Java 8 allows for cleaner code using lambda expressions,


reducing verbosity and improving readability.

6.
Abstracting Over List Type

- Expanded the filter method to handle multiple types (not


just `Apple`), increasing general applicability.

Real-World Applications

- Examples of behavior parameterization in the Java API:


-
Sorting with Comparator
: Allows dynamic sorting criteria to be passed.
-

Scan to Download
Executing Code with Runnable
: Represents code executed in threads.
-
Returning Results with Callable
: Models tasks that yield results, improving on Runnable.
-
GUI Event Handling
: Parameterizes event responses through interfaces.

Conclusion

- Behavior parameterization enhances code adaptability to


changing requirements.
- While Java 8 lambdas aid in reducing verbosity, the core
concept of behavior parameterization allows methods to
accept diverse behaviors, greatly simplifying code
maintenance and readability.

Scan to Download
Example
Key Point:Embrace behavior parameterization to
enhance adaptability in your code.
Example:Imagine you're developing a new app, and
your client suddenly requests changes to the filtering
options. Instead of rewriting existing code, by
implementing behavior parameterization, you can easily
pass different criteria for filtering items, such as color or
size, allowing you to quickly adapt the application's
functionality without extensive modifications. This
approach not only saves time but also keeps your code
clean and maintainable.

Scan to Download
Critical Thinking
Key Point:The Flexibility of Behavior
Parameterization
Critical Interpretation:The chapter highlights behavior
parameterization as an essential design pattern in
software development, enabling flexibility in code
adaptation. While this perspective underscores its
benefits in managing changing requirements, it's crucial
to consider the potential downsides, such as increased
complexity and maintenance challenges that may arise
from too much parameterization. For instance, overly
generalized code can lead to less clarity, making it
difficult for developers to understand intent, which is a
common critique in software engineering discussions
(e.g., see 'Code Complete' by Steve McConnell).
Therefore, while the concept is valuable, readers should
be cautious not to universally apply it without
considering context and potential trade-offs.

Scan to Download
Chapter 5 Summary : 3 Lambda
expressions
Section Content

Overview This chapter introduces lambda expressions in Java 8, contrasting them with anonymous classes.

Lambdas in a
Nutshell Definition: An anonymous function that can be passed around.
Components: Anonymous, function-like, passed as arguments or stored, concise.
Example: Converting a Comparator implementation using anonymous classes to a lambda
expression.

Where and How to Used primarily in functional interfaces, which have a single abstract method.
Use Lambdas

Creating Java 8 provides built-in functional interfaces like Predicate, Consumer, and Function. Specialized
Functional interfaces for primitive types avoid boxing.
Interfaces

Using Lambdas in Execute-Around Pattern: How to use lambdas for parameterizing behavior in resource management.
Practical Scenarios

Type Checking The compiler uses context to determine target type and requires local variables to be final or effectively
and Inference final.

Method Provide concise syntax for existing method calls as lambdas, improving code clarity.
References

Composing Functional interfaces enable combinations of lambda expressions with default methods. Composing
Lambdas functions using andThen and compose; composing comparators with reversed and thenComparing.

Conclusion Lambda expressions and functional interfaces enhance code clarity and maintainability, facilitating
behavior parameterization.

Key Takeaways Lambda expressions improve readability and flexibility; they work with functional interfaces and reduce
verbosity with method references.

Chapter 5 Summary: Lambda Expressions

Overview

Scan to Download
This chapter introduces lambda expressions, a feature in Java
8 that enhances code flexibility and conciseness by enabling
behavior parameterization. It contrasts lambda expressions
with anonymous classes, highlighting the verbosity and
limitations of the latter.

Lambdas in a Nutshell

-
Definition
: A lambda expression is an anonymous function that can be
passed around. It comprises parameters, a body, an optional
return type, and can throw exceptions.
-
Components
:
- Anonymous (no name)
- Function-like (functionality without being directly tied to
a class)
- Passed around as arguments or stored in variables
- Concise compared to anonymous classes
-
Example
: Converting a Comparator implementation using anonymous

Scan to Download
classes into a lambda expression for clarity.

Where and How to Use Lambdas

- Lambda expressions are primarily used in the context of


functional interfaces—interfaces with a single abstract
method (e.g., Predicate, Comparator).
-
Functional Interface
: An interface containing one abstract method, enabling
inline implementation of methods via lambdas.

Creating Functional Interfaces

- Java 8 provides built-in functional interfaces such as:


- `Predicate<T>`: Boolean expression interface
- `Consumer<T>`: Performs actions on objects without
returning values
- `Function<T, R>`: Represents a function mapping one
type to another
- New specialized functional interfaces exist for primitive
types, avoiding boxing.

Scan to Download
Using Lambdas in Practical Scenarios

-
Execute-Around Pattern
: Demonstrates how to parameterize behavior (like
processing file streams) using lambdas for resource
management.

Type Checking and Inference

- The compiler determines the target type expected for a


lambda based on context, enabling type inference.
- Local variables captured in lambdas must be final or
effectively final.

Method References

- Method references provide concise syntax by allowing


existing method calls to be passed as lambdas (e.g.,
`Apple::getWeight` for a method reference).
- This adds clarity and brevity to code.

Composing Lambdas

Scan to Download
- Functional interfaces contain default methods enabling
combinations of multiple lambda expressions.
-
Composing Functions
: Using `andThen` and `compose` methods to create more
complex processing.
-
Composing Comparators
: Methods like `reversed` and `thenComparing` allow for
more sophisticated sorting strategies.

Conclusion

The chapter emphasizes the value of lambda expressions and


functional interfaces in producing clearer, more maintainable
Java code. They facilitate behavior parameterization and
streamline the implementation of functionality in various
contexts.

Key Takeaways

- Lambda expressions enhance code readability and


flexibility.

Scan to Download
- They work closely with functional interfaces, which define
single abstract methods.
- Java provides several built-in functional interfaces to
streamline lambda usage.
- Method references act as shorthand for lambda expressions,
improving clarity and reducing verbosity.

Scan to Download
Example
Key Point:Lambda Expressions Enhance Code
Readability and Flexibility
Example:Imagine you are developing a coffee shop
application and need a way to calculate prices using
discounts. Instead of creating an entire class to
implement different pricing strategies, you can simply
pass lambda expressions like `(price) -> price * 0.9` for
a 10% discount. This concise syntax keeps your code
clean and helps others quickly understand how
discounts are applied without diving into complex class
structures.

Scan to Download
Critical Thinking
Key Point:The distinction between lambda
expressions and anonymous classes emphasizes code
clarity.
Critical Interpretation:The chapter makes a strong
argument supporting the adoption of lambda
expressions over anonymous classes, asserting that
lambdas enhance readability and maintainability of Java
code. However, it may overlook certain scenarios where
anonymous classes are more suitable, such as when
concrete types are necessary or when capturing
additional context is critical. Readers should consider
that while lambda expressions bring significant benefits,
they may introduce complexity in debugging and
understanding for those less familiar with the concepts.
A broader exploration of these trade-offs can be found
in "Effective Java" by Joshua Bloch, which discusses
choice considerations in Java programming.

Scan to Download
Chapter 6 Summary : 4 Introducing
streams
Section Summary

Overview of Streams Streams simplify data manipulation in Java applications, making operations akin to database
queries easier.

What are Streams? Streams treat data collections as pipelines for processing, allowing for intuitive manipulation
and parallel processing.

Java Stream Example Java 8 streams simplify operations like filtering and sorting into single pipelines, contrasting
with the more complex approach in Java 7.

Benefits of Streams

Declarative Code: Users specify "what" to achieve, reducing complexity.


Chaining Operations: Clearer and more readable code through chained operations.
Parallelizable: Improved performance by leveraging multicore architectures.

Key Characteristics of
Streams
Sequence of Elements: Focused on computations, not storage.
Data-Processing Operations: Supports filter and map using functional programming.
Pipelining: Allows for chaining with optimizations like laziness.
Internal Iteration: Automatically handles iteration, unlike collections.

Differences Between
Streams and Collections
Eager vs. Lazy Evaluation: Collections are constructed eagerly, streams compute on
demand.
Single Traversal: Streams can be iterated once only.
Internal vs. External Iteration: Streams manage iteration internally.

Stream Operations

Intermediate Operations: Return another stream and execute upon terminal operation.
Terminal Operations: Produce results and close the stream.

Stream Operations Understanding various intermediate and terminal operations allows effective utilization of
Summary streams in data processing.

Conclusion Java's Streams API enhances collection manipulation, promoting declarative, composable, and
parallelizable code while simplifying traditional operations.

Scan to Download
Chapter 6 Summary: Introducing Streams

Overview of Streams

Java applications commonly utilize collections for grouping


and processing data; however, manipulating collections can
be cumbersome, especially for operations akin to database
queries. Streams were introduced in Java to simplify these
operations, allowing for declarative manipulation of data.

What are Streams?

Streams allow for manipulation of data collections in a more


intuitive way by treating them as pipelines for processing
sequences of elements. They support parallel processing
without requiring multithreaded code.

Java Stream Example

Install
In Java Bookey
7, filtering andApp toaUnlock
sorting collectionFull Textrequired
of dishes and
Audio
multiple steps and intermediate variables. With Java 8
streams, this is simplified into a single pipeline of operations.

Scan to Download
Chapter 7 Summary : 5 Working with
streams

Chapter 7: Working with Streams

Introduction

This chapter introduces the concept of streams in Java,


showcasing the transition from external to internal iteration,
and highlighting the advantages of using the Streams API in
data processing.

Key Topics Covered

- Filtering, slicing, and mapping


- Finding, matching, and reducing
- Using numeric streams
- Creating streams from multiple sources
- Infinite streams

Filtering

Scan to Download
-
Filtering with a Predicate
: The `filter` method allows users to create streams of
elements that match a specified condition.
```java
List<Dish> vegetarianMenu = menu.stream()
.filter(Dish::isVegetarian)
.collect(toList());
```
-
Distinct Elements
: The `distinct` method returns a stream containing only
unique elements.

Slicing a Stream

-
Using takeWhile and dropWhile (Java 9)
: These methods help efficiently select or skip elements
based on a predicate.
```java
List<Dish> slicedMenu1 = specialMenu.stream()
.takeWhile(dish -> dish.getCalories() < 320)

Scan to Download
.collect(toList());
```
-
Truncating and Skipping
: The `limit` and `skip` methods manage the number of
elements processed in a stream.

Mapping

-
Applying Functions
: The `map` method transforms each element in the stream,
allowing users to extract attributes like lengths or names.
```java
List<Integer> dishNameLengths = menu.stream()
.map(Dish::getName)
.map(String::length)
.collect(toList());
```
-
Flattening Streams
: The `flatMap` method is used to flatten nested structures
into a single stream.

Scan to Download
Finding and Matching

- The chapter discusses methods like `anyMatch`, `allMatch`,


`noneMatch`, `findFirst`, and `findAny` to check properties
and retrieve elements in a stream.

Reducing

-
Combining Elements
: The `reduce` method aggregates elements in a stream to
produce a single result, such as summing numbers or finding
maximum values.

Numeric Streams

- Specialized streams like `IntStream`, `DoubleStream`, and


`LongStream` provide performance benefits for numerical
operations without boxing costs.
-
Creating Streams from Ranges
: The `range` and `rangeClosed` methods help generate
sequences of numbers efficiently.

Scan to Download
Building Streams

- Streams can be created from various sources: fixed values


with `Stream.of`, arrays with `Arrays.stream`, and files using
the NIO package.
-
Infinite Streams
: The `iterate` and `generate` methods allow users to create
potentially infinite streams based on functions.

Conclusion

The chapter emphasizes the versatility and power of streams


in processing collections, highlighting their efficiency and
expressiveness in Java programming. Various operations
supported by the Streams API enable complex data
manipulation scenarios to be expressed succinctly.

Scan to Download
Example
Key Point:Use of Streams API
Example:The Streams API in Java transforms how you
handle collections, allowing for simplified data
manipulation through functional programming patterns.
Key Point:Internal vs External Iteration
Example:Switching from external to internal iteration
enhances code readability and efficiency, enabling a
more declarative style of programming.
Key Point:Stream Operations
Example:Operations like filtering and mapping
empower you to express complex data transformations
with minimal code, increasing productivity.
Key Point:Performance Benefits
Example:Utilizing specialized numeric streams can
significantly boost performance in mathematical
computations, reducing overhead associated with
boxing.
Key Point:Flexibility of Stream Sources

Scan to Download
Example:The ability to create streams from diverse
sources, including infinite streams, expands the
potential for innovative solutions in data processing.
Chapter 8 Summary : 6 Collecting data
with streams
Section Summary

Introduction to Streams in Java 8 enable data collection and manipulation using a functional style, categorized into
Streams intermediate (non-consuming) and terminal (consuming) operations.

Key Topics Focus on creating and utilizing collectors, various reduction methods like summarization, grouping,
partitioning, and custom collectors.

Collectors The `collect` method uses collectors for data accumulation, with examples like groupingBy and
Overview partitioningBy.

Reducing Data Reduction operations yield a single value from a stream, including methods such as `counting`, `maxBy`,
and `summingInt`.

Group and Grouping creates nested maps, while partitioning divides elements based on a boolean criterion.
Partitioning Data

Manipulating Grouped elements can be filtered or transformed with additional collectors like `filtering` or `mapping`.
Grouped Elements

Custom Collectors Developers can implement their own collectors through the Collector interface, with methods like
`supplier()`, `accumulator()`, and an example being PrimeNumbersCollector.

Performance Custom collectors can improve performance, such as enhancing prime number checking efficiency.
Considerations

Conclusion Java 8's functional-style programming with the Streams API promotes concise, readable, and
maintainable code compared to traditional approaches.

Collecting Data with Streams

Introduction to Streams

- Streams in Java 8 facilitate data collection and manipulation


using a functional style.

Scan to Download
- Two operational categories:
- Intermediate Operations: Do not consume the stream (e.g.,
filter, map).
- Terminal Operations: Consume the stream and produce a
result (e.g., count, forEach, collect).

Key Topics

- Creating and utilizing collectors via the Collectors class.


- Various reduction methods including summarization,
grouping, partitioning, and custom collectors.

Collectors Overview

- The `collect` method accumulates the results from a stream


using collectors, which are recipes for data accumulation
defined by the Collector interface.
- Examples of collectors include:
-
groupingBy
: Groups elements based on a specified property.
-
partitioningBy
: Partitions elements based on a boolean criterion.

Scan to Download
Reducing Data

- Reduction operations allow for calculating a single value


from a stream (e.g., summing, averaging).
- Examples include `counting`, `maxBy`, and `summingInt`.

Group and Partitioning Data

-
Grouping
: Can create a complex structure of nested maps (e.g., group
dishes by type and calories).
-
Partitioning
: A specific type of grouping that results in a boolean map,
dividing elements into two groups.

Manipulating Grouped Elements

- After grouping, elements can be filtered or transformed


using additional collectors like `filtering` or `mapping`.

Custom Collectors

Scan to Download
- Developers can create their own collectors by implementing
the Collector interface, which includes methods such as
`supplier()`, `accumulator()`, `finisher()`, `combiner()`, and
`characteristics()`.
- Example of a custom collector:
PrimeNumbersCollector
, which divides integers into prime and non-prime categories.

Performance Considerations

- Custom collectors can enhance performance; for instance,


improving prime checking by only testing against previously
found primes.

Conclusion

- Overall, functional-style programming in Java 8, alongside


the Streams API, allows for more concise, readable, and
maintainable code compared to traditional imperative
programming styles.

Scan to Download
Example
Key Point:Utilizing Streams and Collectors for Data
Manipulation
Example:Imagine you're processing a list of student
grades; with Streams, you can seamlessly group these
grades by passing a simple lambda expression, allowing
you to quickly calculate averages, filter out failing
grades, or even partition students into categories, all
with minimal and readable code.

Scan to Download
Critical Thinking
Key Point:Functional Programming in Java 8
Critical Interpretation:The chapter emphasizes the
benefits of functional programming through streams, yet
this approach has both advocates and detractors in the
programming community. While proponents argue that
it leads to cleaner, more maintainable code, critics
contend that it may obscure the logic for those
unfamiliar with functional paradigms, resulting in
possible misunderstandings. This duality in
interpretation suggests that while the author's positive
view on streams in Java 8 is valid and supported (e.g., in
works by Martin Fowler or in Java documentation
itself), developers should be mindful that the
effectiveness of functional programming techniques can
vary significantly based on context and individual
developer experience.

Scan to Download
Chapter 9 Summary : 7 Parallel data
processing and performance

Summary of Chapter 9: Parallel Data Processing


and Performance

Introduction

This chapter focuses on utilizing the Streams interface in


Java to process collections of data in a parallel manner. It
highlights the transition from external to internal iteration,
enhancing performance and enabling automatic parallel
execution leveraging multi-core processors.

Key Concepts

-
Parallel Streams
: Developers can easily turn a collection into a parallel
stream using `parallelStream()`, enabling concurrent
processing of elements through multiple threads.

Scan to Download
-
Fork/Join Framework
: Java 7 introduced this framework to support parallel
processing efficiently. It allows tasks to be split into
subtasks, processed in parallel, and results combined.
-
Spliterators
: A key component in parallel streams responsible for
dividing the data into chunks that can be processed
simultaneously.

Parallel Streams

- Convert sequential streams to parallel using `parallel()`.


- Performance improvements are expected on large data sets.
- Understanding the splitting process is crucial, as improper
use can lead to incorrect results.

Performance Measurement

- To assess the efficiency of parallel processing, developers


Install
should Bookey
utilize App to
benchmarking Unlock
tools Full
like JMH Text and
(Java
Microbenchmark Harness).Audio
- It's essential to evaluate and avoid assumptions regarding

Scan to Download
Chapter 10 Summary : 8 Collection API
enhancements

Collection API Enhancements

Java's Collection API is crucial for developers and is widely


used in applications. However, it has past limitations that
made it verbose and prone to errors. This chapter explores
enhancements introduced in Java 8 and 9 to simplify the
creation and manipulation of collections.

Introduction to Collection Factories

- Java 9 introduces factory methods for creating immutable


lists, sets, and maps, making collection initialization easier
and more concise.
- Instead of verbose implementations, methods like `List.of`,
`Set.of`, and `Map.of` allow for straightforward creation of
collections without unnecessary boilerplate code.

Creating Collections with Factory Methods

Scan to Download
1.
List Factory

- Use `List.of` to create immutable lists.


- Attempting to modify these lists (e.g., adding or replacing
elements) raises an `UnsupportedOperationException`.
2.
Set Factory

- Similar to lists, `Set.of` ensures collections are immutable


and raises exceptions for duplicate elements.
3.
Map Factory

- `Map.of` and `Map.ofEntries` provide a way to easily


create immutable maps with key-value pairs.

Working with List and Set

- Java 8 introduces methods like `removeIf` (to remove


elements based on a predicate), `replaceAll` (to modify
elements), and `sort` (to arrange elements in order).
- These methods simplify collection manipulation and reduce
verbosity while protecting against common errors like

Scan to Download
`ConcurrentModificationException`.

Working with Map

- Enhancements include:
-
forEach
: Iterates through map entries neatly with a `BiConsumer`.
-
Sorting
: Use `Entry.comparingByKey` and
`Entry.comparingByValue` to sort map entries conveniently.
-
getOrDefault
: Retrieves a default value if the specified key is absent,
avoiding null checks.
-
Compute Patterns
: Includes `computeIfAbsent`, `computeIfPresent`, and
`compute`, allowing conditional operations to manage
key-value pairs.
-
Remove Patterns
: New versions of the `remove` method improve how entries

Scan to Download
are deleted based on their associated values.
-
Replace Patterns
: Methods like `replaceAll` and `replace` enable bulk and
conditional updates respectively.
-
Merge
: Combines entries from two maps with flexible handling of
duplicates.

Improved ConcurrentHashMap

- Introduced to support concurrency more efficiently than


traditional synchronized approaches.
- New operations like `forEach`, `reduce`, and `search`
enhance functionality while processing concurrently.
- Features such as `mappingCount` provide a reliable way to
count entries, and `keySet` offers a synchronized view of the
map as a set.

Summary of Key Points

- Java 9 simplifies collection creation with factory methods


for immutable collections.

Scan to Download
- Java 8 added useful methods for easier manipulation of
lists, sets, and maps.
- ConcurrentHashMap provides enhanced performance for
concurrent operations, offering thread-safe methods that
align with the new enhancements in Maps.

Scan to Download
Critical Thinking
Key Point:The introduction of factory methods to
create immutable collections in Java 9 is
revolutionary.
Critical Interpretation:While the new factory methods
like List.of and Set.of aim to simplify collection
initialization and reduce the likelihood of errors, one
could argue that the emphasis on immutability might
limit flexibility. For instance, requiring developers to
rethink how they handle collection modifications may
lead to unexpected complications in existing codebases.
Critics might suggest that although immutability is often
beneficial in concurrent programming, it also imposes a
stricter programming paradigm which some developers
might resist. Furthermore, the rigid structure of
immutable collections may not suit all use cases,
particularly those requiring dynamic modifications.
Therefore, while these enhancements represent a
significant advancement in Java's Collection API,
developers should critically evaluate their
appropriateness for specific contexts. Sources such as

Scan to Download
Chapter 11 Summary : 9 Refactoring,
testing, and debugging
Section Content

Chapter Title Refactoring, Testing, and Debugging

Overview Discusses the role of lambda expressions and Streams API in refactoring code for
readability and flexibility, along with testing and debugging strategies.

Refactoring for Improved


Readability and Flexibility Lambda Expressions: Concise coding by replacing anonymous classes.
Improving Readability: Techniques for readability include:
- Transforming anonymous classes to lambda expressions.
- Replacing lambda expressions with method references.
- Using Streams API for data processing.
Improving Code Flexibility: Encourages behavior parameterization with predicates
or comparators.

Refactoring Object-Oriented
Design Patterns Design Patterns Simplified by Lambdas: Simplifies patterns like:
- Strategy Pattern: Use lambda instead of concrete classes.
- Template Method Pattern: Use lambdas for customizable algorithms.
- Observer Pattern: Simplifies observer behavior.
- Chain of Responsibility: Uses composed lambda functions.
- Factory Pattern: Simplifies object instantiation with method references.

Testing Lambdas
Emphasizes unit testing for correctness, with strategies such as:
- Direct testing of lambda expressions via functional interfaces.
- Focusing on methods that utilize lambdas.
- Separating complex lambdas for easier testing.

Debugging
Addresses challenges with debugging lambdas, recommending:
- Using `peek` for logging intermediate stream values.
- Observing stack traces to isolate issues with lambda naming conventions.

Summary Lambda expressions improve readability and flexibility, simplify design patterns, and
require careful testing and debugging strategies.

Chapter 11: Refactoring, Testing, and Debugging

Scan to Download
In this chapter, the role of lambda expressions and the
Streams API in refactoring existing Java code is discussed.
The focus is on making code more readable and flexible
while offering strategies for testing and debugging.

Refactoring for Improved Readability and


Flexibility

-
Lambda Expressions
: Lambda expressions allow for concise and flexible coding
by replacing verbose anonymous classes. Several techniques
for improving code readability are proposed, such as
refactoring anonymous classes to lambda expressions,
converting lambda expressions to method references, and
using the Streams API for data processing.
-
Improving Readability
: Code readability can be improved through well-documented
code and adherence to coding standards, with Java 8 features
enabling reduced verbosity. Tips for improving readability
through three refactoring techniques are outlined:
- Transforming anonymous classes to lambda expressions.
- Replacing lambda expressions with method references.

Scan to Download
- Using the Streams API for declarative data processing.
-
Improving Code Flexibility
: Lambdas encourage behavior parameterization, allowing for
flexible responses to requirement changes, such as using
predicates or comparators.

Refactoring Object-Oriented Design Patterns with


Lambdas

-
Design Patterns
: Lambda expressions can simplify classic design patterns
like Strategy, Template Method, Observer, Chain of
Responsibility, and Factory, reducing necessary boilerplate
code.
-
Strategy Pattern
: Instead of creating multiple concrete classes for algorithms,
pass lambda expressions that implement required behavior.
-
Template Method Pattern
: Replace abstract classes with lambda parameters for
customizable algorithm parts.

Scan to Download
-
Observer Pattern
: Use lambda expressions for observer behavior, eliminating
the need for dedicated classes when the logic is simple.
-
Chain of Responsibility
: Simplify chained processing with composed lambda
functions.
-
Factory Pattern
: Use method references for constructor calls, removing
complexity in object instantiation.

Testing Lambdas

- The chapter emphasizes unit testing as a means to ensure


code correctness. It outlines strategies to test behaviors
associated with lambda expressions, encouraging indirect
testing of methods that utilize lambdas rather than the
lambdas themselves.
- Strategies include:
- Direct testing of accessible lambda expressions through
functional interfaces.
- Focusing tests on methods employing lambda

Scan to Download
expressions.
- Separating complex lambdas into named methods for
easier testing.

Debugging

- Debugging challenges with lambdas and streams are


addressed, particularly the obscurity in stack traces caused by
unnamed lambdas.
- Recommendations for debugging include:
- Using `peek` for logging intermediate stream values for
clarity.
- Observing stack traces to isolate issues, with emphasis on
recognizing lambda-related naming conventions.

Summary

- Lambda expressions enhance code readability and


flexibility while providing avenues for more straightforward
implementation of established design patterns.
- Testing and debugging strategies focus on ensuring the
reliability of code that incorporates lambdas, highlighting the
need for careful consideration of code structure during
development.

Scan to Download
Example
Key Point:Improving code readability and flexibility
with lambda expressions.
Example:Imagine you are tasked with updating a
complex Java application. Instead of battling with
lengthy anonymous classes, you breathe easy as you
switch to simple lambda expressions. This
transformation not only makes your code cleaner and
easier to read but also allows you to adapt quickly to
any changes in requirements by easily modifying the
behavior of your functions. As a result, your code is not
just functional; it becomes elegant and maintainable,
inviting further enhancements and collaboration.

Scan to Download
Critical Thinking
Key Point:Lambda expressions and the Streams API
enhance code readability and flexibility in Java
development.
Critical Interpretation:While the author asserts that
lambda expressions significantly improve the readability
and flexibility of Java code, this perspective may
oversimplify the debugging complexities intrinsic to
functional programming. Notably, lambda expressions
can obfuscate stack traces and hinder error tracing,
which is a concern not adequately addressed in the
summary. Additionally, while the concise syntax might
appeal to some developers, others argue that this can
lead to less maintainable code if overused without
proper documentation (Petersen et al., 2018). It's crucial
for readers to consider these potential drawbacks and
balance the advantages of lambda expressions with the
need for clear debugging and testing practices.

Scan to Download
Chapter 12 Summary : 10
Domain-specific languages using
lambdas
Section Content

Introduction Discusses the role of DSLs in enhancing clarity and understanding between technical and non-technical
stakeholders.

Understanding DSLs are tailored programming languages for specific domains using domain-specific terminology,
DSLs facilitated by Java lambda expressions. Includes benefits, drawbacks, and examples of internal and
external DSLs.

Benefits of DSLs

Conciseness
Readability
Maintainability
Abstraction
Focus
Separation of Concerns

Drawbacks of
DSLs
Design Difficulty
Development Cost
Indirection Layer
Learning Curve
Language Limitations

DSL Solutions on
the JVM
Internal DSLs
Polyglot DSLs
External DSLs

Practical Discusses methods like method chaining, nested functions, and function sequencing using lambdas to
Implementations of implement DSLs and enhance readability.
DSLs in Java

Patterns for
Creating DSLs
Method Chaining
Nested Functions
Function Sequencing with Lambdas

Scan to Download
Section Content

Real-world
Examples of DSLs
jOOQ - SQL queries DSL emphasizing type safety
Cucumber - BDD framework for structured business scenarios
Spring Integration - Implements Enterprise Integration Patterns through a DSL

Conclusion Highlights the importance of DSLs for enhancing communication and understanding business logic
within development teams.

Domain-Specific Languages Using Lambdas

Introduction

This chapter discusses the role of domain-specific languages


(DSLs) in software development, emphasizing how they
enhance clarity and understanding between technical and
non-technical stakeholders.

Understanding DSLs

- DSLs are small programming languages tailored to specific


domains, utilizing domain-specific terminology.
- The Java introduction of lambda expressions makes it easier
to create more readable DSLs.
- The chapter includes benefits and drawbacks of using

Scan to Download
DSLs, as well as exploring internal and external DSL
solutions, with practical examples.

Benefits of DSLs

- Conciseness: Reduces code verbosity by encapsulating


business logic.
- Readability: Facilitates understanding by using
domain-specific vocabulary.
- Maintainability: Improves ease of code maintenance,
especially for frequently changing business-related code.
- Abstraction: Allows operations to align with domain
concerns, hiding system-level complexities.
- Focus: Keeps programmers concentrated on business rules,
enhancing productivity.
- Separation of Concerns: Isolates business logic from
infrastructure, making maintenance easier.

Drawbacks of DSLs

- Design Difficulty: Capturing domain knowledge concisely


canInstall Bookey App to Unlock Full Text and
be challenging.
- Development Cost: High Audio
initial overhead can delay
projects, necessitating long-term investment.

Scan to Download
Chapter 13 Summary : 11 Using
Optional as a better alternative to null

Using Optional as a Better Alternative to Null

Introduction

- NullPointerExceptions are a common frustration among


Java developers.
- This chapter discusses the drawbacks of using null
references, and how Java's `Optional` class provides a safer
alternative.

The Problem with Null

- Null references are easy to implement, but they lead to


numerous programming errors and decreased readability.
- Tony Hoare, who introduced null references, later called it a
“billion-dollar mistake,” acknowledging its significant costs
to developers.

Scan to Download
Modeling Absence of Value

- A typical example involves nested object structures,


demonstrating how null values lead to
`NullPointerExceptions`.
- Defensive programming can reduce errors but can result in
overly complicated and hard-to-read code.

Why You Should Avoid Null

- Nulls cause errors, complexity, and lack semantic meaning


in the context of statically typed languages.
- Null references disrupt the philosophy of Java and create
holes in the type system.

Alternatives to Null

- Other programming languages offer solutions, such as


Groovy's safe navigation operator and Haskell's Maybe type.
- Java 8 introduces `Optional<T>`, inspired by these
concepts.

Introducing the Optional Class

Scan to Download
- `Optional<T>` encapsulates an optional value, offering
clear indications of potential absence.
- Instead of allowing null references, using `Optional<Car>`
signifies that the car might be missing.

Patterns for Adopting Optionals

- You can create `Optional` instances using


`Optional.empty()`, `Optional.of()`, and
`Optional.ofNullable()`.
- Use `map` to extract values from `Optionals`, and `flatMap`
for chaining operations that result in another `Optional`.

Using Optionals in Domain Models

- Although `Optional` enriches domain semantics, it is not


serializable and should be used judiciously in models.
- A method returning `Optional<Car>` allows for a consistent
approach to handle presence checks.

Manipulating Streams of Optionals

- Java 9 introduced a method to convert an `Optional` to a


`Stream`, allowing for efficient filtering and mapping.

Scan to Download
- You can streamline processing by handling potential absent
values in a single operation.

Default Actions and Unwrapping Optionals

- `Optional` provides several methods to extract values


safely:
- `orElse(T other)` for default values,
- `orElseGet(Supplier<? extends T> supplier)` for lazy
initialization,
- `ifPresent(Consumer<? super T> consumer)` for
executing actions conditionally.

Rejecting Values with Filter

- The `filter` method allows for checking properties of the


value in an `Optional`, promoting cleaner code.

Practical Examples

- Wrap null-returning methods to integrate an optional


pattern seamlessly into existing Java APIs.
- Transform methods like `String.parseInt` to return an
`Optional<Integer>` instead of throwing exceptions.

Scan to Download
Summary

- Null references have historical significance but are fraught


with issues, and modern development practices favor the use
of `Optional<T>`.
- Using `Optional` improves code safety, readability, and
semantically conveys method expectations, ultimately
leading to more robust API design.

Scan to Download
Example
Key Point:Utilizing `Optional` prevents
NullPointerExceptions and offers a more expressive
way to handle absence of values.
Example:Imagine you’re developing an application to
manage users. You decide that when searching for a
user's profile, instead of returning a null value if the user
doesn’t exist, you use `Optional<User>`. This way,
when you call `findUserById(userId)`, you explicitly
acknowledge that a user might not be present. Using
`userOptional.ifPresent(user -> displayUser(user));`
makes it clear you safely handle the absence - if the user
exists, it’s shown; if not, no error occurs, keeping your
code cleaner and more intuitive.

Scan to Download
Critical Thinking
Key Point:The Limitations of `Optional` in Java
Critical Interpretation:While the use of `Optional` as a
null alternative is advocated for improving code safety,
one must consider its limitations and the author's
emphasis may not capture the practical challenges
developers face. Despite its advantages, `Optional` can
lead to inefficiencies, especially in
performance-sensitive applications, as creating multiple
`Optional` instances could introduce overhead.
Furthermore, while the `Optional` class enriches the
semantics of code, it can also complicate method
signatures and confuse developers who may
misinterpret its intended use, leading to improper
implementations. Critics argue that it bypasses the
fundamental problem of null references rather than
addressing it wholly (see 'Effective Java' by Joshua
Bloch for a nuanced discussion). Hence, readers should
critically evaluate how `Optional` is integrated within
particular contexts rather than accepting it as a universal
solution to null references.

Scan to Download
Chapter 14 Summary : 12 New Date and
Time API

Chapter 14: New Date and Time API

Introduction

- The Java API had significant shortcomings in date and time


management prior to Java 8.
- Java 8 introduced a new Date and Time API to address
these issues, featuring improved usability and fewer design
flaws.

Historical Context

- The original java.util.Date class had limitations, such as


starting years from 1900 and months from index 0.
- Java 1.1 introduced java.util.Calendar as an alternative, but
it had similar problems.
- As a result, developers often resorted to third-party libraries
like Joda-Time.

Scan to Download
Key Features of the New Date and Time API

- The new API includes several classes: LocalDate,


LocalTime, LocalDateTime, Instant, Duration, and Period.

Working with LocalDate and LocalTime

-
LocalDate
: Immutable object representing a date without time or
timezone information.
- Creation: `LocalDate date = LocalDate.of(2017, 9, 21);`
-
LocalTime
: Represents time without date or timezone.
- Creation: `LocalTime time = LocalTime.of(13, 45, 20);`
- Both classes provide methods to access their values and
support parsing from strings.

Combining Date and Time

-
LocalDateTime

Scan to Download
combines both date and time information without a
timezone.
- Creation examples include using the `of` method with date
and time components.

Instant Class

- Represents an exact point in time for machines, expressed


as seconds since the Unix epoch.
- Creation: `Instant instant = Instant.now();`

Defining Duration and Period

-
Duration
: Measures time in seconds and nanoseconds.
-
Period
: Measures time in years, months, and days.
- Both classes support methods for creating instances directly
or based on differences between temporal objects.

Manipulating Dates and Times

Scan to Download
- The API supports modifying dates and times through
functional updates, offering methods like `with`, `plus`, and
`minus`.

Working with TemporalAdjusters

-
TemporalAdjusters
allow for complex date manipulations, such as finding the
next Sunday or last day of the month.
- Custom adjusters can be implemented through the
`TemporalAdjuster` interface.

Formatting and Parsing

- The `DateTimeFormatter` class provides thread-safe


methods to format and parse date-time objects based on
patterns or predefined formats.

Time Zones and Calendars

- The
ZoneId
class replaces the older

Scan to Download
TimeZone
class, simplifying time zone management.
- Time zones can be represented by region IDs or fixed
offsets.
- Support for alternative calendar systems (e.g.,
ThaiBuddhist, Hijrah) allows for localized date handling.

Summary

- The new Date and Time API in Java 8 addresses previous


inconsistencies with immutability and proper design.
- It allows for both human-readable and machine-friendly
date-time representations and offers robust manipulation,
formatting, and localization features.

Scan to Download
Critical Thinking
Key Point:The New Date and Time API offers
significant improvements over previous versions, but
its reliance on immutability raises questions.
Critical Interpretation:While the API addresses many
shortcomings of earlier classes, the push for
immutability may not suit all programming paradigms
or user needs. Developers should critically assess
whether immutability adds actual value in their specific
use cases. This perspective can be supported by
examining critiques in literature about immutable
structures, such as those found in 'The Pragmatic
Programmer' by Andrew Hunt and David Thomas,
which emphasizes context and adaptability in design
decisions.

Scan to Download
Chapter 15 Summary : 13 Default
methods
Section Content

Chapter Title Chapter 15: Default Methods

Overview Default methods in Java 8 allow interfaces to provide method implementations, aiding in API evolution
without breaking existing implementations, thus maintaining backward compatibility.

What Are Default Default methods include method bodies in interfaces. Implementing classes inherit these unless
Methods? overridden. Examples are the `sort` method in List and `stream` in Collection.

Evolving APIs Adding new methods can break implementations, but default methods allow these methods to have
default behaviors, maintaining compatibility. Use the `default` keyword to declare them.

Usage Patterns for


Default Methods
Optional Methods: Reduce boilerplate by providing implementations for optional methods, e.g.,
`remove` in Iterator.
Multiple Inheritance of Behavior: Enables code reuse without duplication by inheriting from
multiple interfaces.

Resolution Rules

Class methods take priority over interface methods.


The most specific interface method prevails if no class method exists.
Ambiguities require explicit overriding in the class.

Key Concepts Default methods enhance interfaces, allowing method definitions, ensuring backward compatibility, and
encouraging efficient and orthogonal designs.

Conclusion Default methods are a significant enhancement in Java 8 for evolving APIs, reducing boilerplate, and
allowing multiple interface implementations while providing tools for managing conflicts.

Chapter 15: Default Methods

Overview

Scan to Download
Default methods in Java 8 allow interfaces to provide method
implementations. This feature helps library designers evolve
APIs without requiring modifications to existing
implementing classes, reducing issues related to backward
compatibility.

What Are Default Methods?

- Default methods allow interfaces to include method bodies.


- Implementing classes inherit default implementations from
interfaces unless they provide their own.
- Examples include the `sort` method in the List interface and
the `stream` method in the Collection interface.

Evolving APIs

- Adding a new method to an existing interface can break


existing implementations.
- Default methods help avoid issues by allowing new
methods to have default behaviors that existing
Install Bookey
implementations App to Unlock
can automatically use. Full Text and
- Methods can be declared Audio
as default using the `default`
keyword.

Scan to Download
Chapter 16 Summary : 14 The Java
Module System

The Java Module System

Introduction

The Java Module System, introduced in Java 9 as part of


Project Jigsaw, enhances the organization and encapsulation
of code, addressing the limitations of previous
modularization methods in Java.

Chapter Overview

- Evolutionary forces leading to the adoption of a module


system
- Structure of modules, including declarations and directives
(requires, exports)
- Automatic modules for legacy JARs
- Modularization of the JDK library
- Integration with Maven builds

Scan to Download
1. The Driving Force: Reasoning About Software

Understanding modularity is crucial for enhancing


productivity and maintainability. Two key principles
underpin effective software design:

1.1 Separation of Concerns (SoC)

SoC promotes dividing a program into distinct modules to


manage different features, enhancing collaboration and
maintenance.

1.2 Information Hiding

This principle stresses the importance of concealing


implementation details to minimize dependencies and avoid
cascading changes, improving security and stability.

2. Why the Java Module System Was Designed

Pre-Java 9 modularization faced limitations such as


inadequate visibility controls and challenges related to class
path complexity. The monolithic nature of the JDK

Scan to Download
exacerbated issues with dependency management and
evolution.

3. Java Modules: The Big Picture

Java 9 introduces modules with the `module-info.java` file


defining module dependencies (requires) and public APIs
(exports), enhancing encapsulation compared to previous
methods.

4. Developing an Application with the Java Module


System

An example modular application demonstrates the


organization of code into distinct modules. Initial steps
include setting up a project structure and utilizing Java
Module System basics.

4.1 Fine-Grained vs. Coarse-Grained


Modularization

Choosing the right granularity for modularization impacts


maintenance and collaboration. A balanced approach is
recommended to avoid excessive complexity or

Scan to Download
encapsulation loss.

4.2 Compiling and Packaging

Instructions for compiling and running modular applications,


detailing usage of commands and the importance of
`module-info.java`.

5. Working with Several Modules

Explains how to enhance the application with additional


modules, using `exports` and `requires` clauses for module
interactions.

6. Automatic Modules

Discusses incorporating legacy libraries into a modular


application as automatic modules, which automatically
export all packages in absence of a `module-info.java`.

7. Module Declaration and Clauses

Overview of additional keywords and clauses available in


module declarations, including `requires-transitive`,

Scan to Download
`exports-to`, `open`, `opens`, `uses`, and `provides`.

8. Summary

- Modularization principles: SoC and information hiding.


- Improvements from Java 9's module system concerning
encapsulation and dependency management.
- Structure defined by `module-info.java` with directives for
explicit dependencies and public APIs.
- Maven's compatibility with the Java Module System for
robust builds.

For an in-depth exploration beyond this overview, consider


the book "The Java Module System" by Nicolai Parlog.

Scan to Download
Example
Key Point:Importance of Modularity in Java
Development
Example:Understanding how to effectively use Java's
module system enables you to design cleaner, more
maintainable applications while avoiding common
pitfalls of dependency management.
Key Point:Encapsulation and Dependency Management
Example:By utilizing concepts like information hiding,
you can structure your project to minimize reliance
between modules, which directly improves security and
future-proofing.
Key Point:Significance of separation of concerns
Example:Adopting the principle of separation of
concerns allows you to isolate features, making your
codebase easier to understand and update, ultimately
speeding up development.
Key Point:Utilizing Java 9's Module System
Example:Implementing the Java Module System's
directives like 'requires' and 'exports' can transform your

Scan to Download
coding practices significantly and enhance application
scalability.
Key Point:Enhancing Collaboration through
Modularization
Example:When developing larger applications,
leveraging modules promotes a collaborative
environment by allowing teams to work independently
on different parts without affecting each other.
Critical Thinking
Key Point:The importance of modularization in
software development.
Critical Interpretation:The chapter emphasizes
modularization through the Java Module System, which
is vital for improving maintainability and organization
within applications. However, it raises the question of
whether these improvements genuinely result in
enhanced productivity or merely create an additional
layer of complexity that inexperienced developers may
struggle with. Critics might argue that the benefits of
modularization can sometimes be overstated, as recent
studies and discussions in software engineering suggest
that over-modularization can lead to fragmented
codebases and increased build times (see 'Refactoring:
Improving the Design of Existing Code' by Martin
Fowler). Thus, while the author's perspective is
grounded in the principles of Separation of Concerns
and Information Hiding, readers are encouraged to
evaluate the practicality and impact of the Java Module
System in diverse development contexts.

Scan to Download
Chapter 17 Summary : 15 Concepts
behind CompletableFuture and reactive
programming

Summary of Chapter 17: Concepts Behind


CompletableFuture and Reactive Programming

This chapter explores two major trends influencing modern


software development: the need for concurrency due to
multicore processors, and the growing reliance on
interconnected services through microservices architecture.

Key Topics Covered:

-
Concurrency and Parallelism
: Discusses how modern applications benefit from parallel
execution of tasks across multiple cores and introduces
Java’s concurrency APIs, including Threads, Futures, and
ExecutorServices.
-
Asynchronous APIs

Scan to Download
: Explains the importance of non-blocking operations,
allowing multiple tasks to run concurrently, thus improving
efficiency. It highlights Java's CompletableFuture for
handling asynchronous tasks and the flow of data in a
reactive programming context.
-
Box-and-Channel Model
: Introduces a visual model for structuring concurrent
systems, representing components as boxes that
communicate through channels. This model aids in designing
clear and maintainable asynchronous systems.
-
CompletableFuture and Combinators
: Discusses the strengths of CompletableFuture in supporting
non-blocking operations through combinators that allow
composition of multiple asynchronous tasks. This improves
readability and eliminates blocking waits.
-
Reactive Programming with the Flow API
: Describes the publish-subscribe architecture introduced in
Java 9, facilitating the handling of data streams in a reactive
manner. It allows systems to respond to changes in real-time
and supports backpressure in managing flow rates between
publishers and subscribers.

Scan to Download
-
Reactive Systems vs. Reactive Programming
: Differentiates between the concepts, emphasizing that a
reactive system is designed to be responsive, resilient, and
elastic, often leveraging reactive programming practices to
achieve these properties.

Conclusion
: The chapter synthesizes these concepts to enhance
developers' ability to create efficient, responsive applications
that utilize modern processing capabilities and handle
multiple asynchronous operations seamlessly. The guidance
provided sets the stage for more detailed exploration in the
following chapters regarding concrete implementations using
the CompletableFuture API and the Flow API.

Scan to Download
Chapter 18 Summary : 16
CompletableFuture: composable
asynchronous programming
Section Summary

Overview Discusses CompletableFuture class in Java 8, enhancing asynchronous programming with modern
concurrency tools.

Key Topics Covered

Creating and retrieving asynchronous computations.


Increasing throughput with nonblocking operations.
Designing asynchronous APIs.
Consuming synchronous APIs asynchronously.
Pipelining and merging asynchronous operations.
Reacting to asynchronous completion.

1. Understanding Futures Describes Future interface limitations in expressing dependencies and task result combinations.
and Limitations

2. Working with Explores CompletableFuture for fluent code style with lambda expressions through an example
CompletableFutures best-price-finder application.

3. Dealing with Errors Explains handling errors with completeExceptionally method in CompletableFuture.

4. Pipelining Introduces discount service processing prices asynchronously with thenCompose and
Asynchronous Tasks thenCombine methods.

5. Building a Points out performance improvements using CompletableFutures and custom Executors for
Nonblocking Solution workload scaling.

6. Implementing Discusses Java 9 methods for managing timeouts with orTimeout and completeOnTimeout in
Timeouts and Fallbacks CompletableFutures.

7. Reacting to Explains immediate responses to CompletableFuture completions, providing incremental results.


CompletableFuture
Completions

Conclusion Summarizes advantages of CompletableFutures for simplifying asynchronous programming and


improving responsiveness, leading into the next chapter about Java 9 Flow API.

CompletableFuture: Composable Asynchronous


Programming

Scan to Download
Overview

This chapter discusses the CompletableFuture class


introduced in Java 8, which enhances the Future interface to
support more declarative asynchronous programming. It
emphasizes the importance of leveraging modern
concurrency tools to exploit multiple processing resources
effectively.

Key Topics Covered

- Creating asynchronous computations and retrieving results.


- Increasing throughput using nonblocking operations.
- Designing and implementing asynchronous APIs.
- Consuming synchronous APIs asynchronously.
- Pipelining and merging asynchronous operations.
- Reacting to the completions of asynchronous operations.

1. Understanding Futures and Limitations


Install Bookey App to Unlock Full Text and
Audio
- The Future interface models asynchronous computations,
allowing threads to remain productive without blocking.

Scan to Download
Chapter 19 Summary : 17 Reactive
programming
Section Description

Reactive Programming Essential for handling big data, operating in heterogeneous environments, and meeting user
expectations for rapid response times.

The Reactive Manifesto Outlines four principles: Responsive, Resilient, Elastic, and Message-driven.

Reactive at Application Focuses on asynchronous task execution and resource maximization in multicore environments.
Level

Reactive at System Allows applications to work cohesively and isolates failures to enhance resilience and elasticity.
Level

Reactive Streams and Introduced in Java 9, this includes Publisher, Subscriber, Subscription, and Processor for
the Flow API nonblocking backpressure.

Creating Reactive Demonstrates a temperature-reporting application using the Flow API for fetching and processing
Applications data reactively.

Using RxJava Enhances the Flow API with Observable tools for creating and manipulating reactive streams,
including mapping and filtering.

Summary Highlights the importance of reactive programming principles and technologies like the Flow API
and RxJava in modern application development.

Reactive Programming

Reactive programming is increasingly essential in modern


software development due to several factors:
-
Big Data
: Modern applications handle large volumes of data measured
in petabytes.
-

Scan to Download
Heterogeneous Environments
: Applications operate across diverse systems, from mobile
devices to cloud clusters.
-
User Expectations
: Users demand rapid response times (millisecond-level) and
high availability.
Reactive programming addresses these challenges by
enabling asynchronous data processing in a responsive
manner. The approach allows applications to react to data as
it arrives, ensuring user interactions are more fluid and
coordinated, even under various network conditions and
workloads.

The Reactive Manifesto

The Reactive Manifesto outlines four core principles of


reactive systems:
-
Responsive
: Ensures predictable response times, enhancing user trust.
-
Resilient
: Remains responsive despite component failures, employing

Scan to Download
techniques such as replication and decoupling.
-
Elastic
: Automatically adapts resource allocation based on
workload.
-
Message-driven
: Uses asynchronous message passing for component
interaction, ensuring loose coupling and isolation.
These principles can be applied at varying scales, influencing
both application-level and system-level structures.

Reactive at Application Level

Reactive programming at the application level focuses on


asynchronous task execution, maximizing resource use in
modern multicore environments. Reactive frameworks share
threads among lighter constructs, avoiding blocking
operations that hinder performance.

Reactive at System Level

At the system level, reactive architectures allow multiple


applications to function cohesively, isolating failures to

Scan to Download
prevent system-wide disruptions. Achieving resilience
involves containing errors, while elasticity is facilitated
through location transparency, enabling seamless scaling
based on demand.

Reactive Streams and the Flow API

Reactive programming employs reactive streams


standardized by the publish-subscribe model. Java 9
introduced the Flow API, incorporating four key interfaces:
Publisher, Subscriber, Subscription, and Processor, which
together implement mandatory nonblocking backpressure.

Creating Reactive Applications

A practical example illustrated the construction of a


temperature-reporting application, showcasing
implementations of the Flow API to enable temperature
fetching and processing through reactive principles.

Using RxJava

RxJava builds on the concepts from the Reactive Manifesto


and Java’s Flow API, offering tools for creating reactive

Scan to Download
applications. It supports additional functionality through
Observables, allowing easier creation and manipulation of
reactive streams, including mapping, merging, and filtering
operations.

Summary

Reactive programming leverages well-established principles


to meet contemporary demands in data handling and
responsiveness. Key takeaways include the adoption of the
Reactive Manifesto's principles, the developed Java 9 Flow
API for standardized reactive streams, and the powerful
features provided by libraries like RxJava for enhancing
reactive application development.

Scan to Download
Example
Key Point:Embracing Reactive Programming is vital
for staying competitive in today's software
landscape.
Example:Imagine you're developing an app that streams
live sports scores. As fans eagerly await updates, your
app leverages reactive programming to receive and
display scores instantly, regardless of network speed.
This ensures your users enjoy real-time interaction that
meets their high expectations for responsiveness,
especially during critical game moments.

Scan to Download
Critical Thinking
Key Point:The necessity of reactive programming in
modern application development.
Critical Interpretation:While the chapter emphasizes the
importance of reactive programming, one might
question whether its widespread adoption is justified
based on all contexts, particularly for simpler
applications where traditional synchronous models
could suffice. Not every application requires the
complexities of reactive systems, as smaller projects or
those with stable data requirements might not benefit
from the overhead associated with reactive principles.
Further critical perspectives can be explored in works
such as 'Designing Data-Intensive Applications' by
Martin Kleppmann, which discusses various
architectural decisions and their implications,
encouraging developers to apply best practices based on
specific project needs rather than a one-size-fits-all
reactive approach.

Scan to Download
Chapter 20 Summary : 18 Thinking
functionally
Section Summary

Introduction to This section introduces the key principles of functional programming in Java, focusing on side effects,
Functional immutability, declarative programming, and referential transparency, along with techniques like
Programming higher-order functions and combinators.

Why Functional Functional programming reduces complexity due to shared mutable data, promoting clearer, more modular
Programming? code.

Defining Functional programming emphasizes side-effect-free functions that consistently produce the same output
Functional for the same input without altering any external state.
Programming

Declarative This methodology focuses on specifying what to achieve rather than how, resulting in clearer and more
Programming concise code.

Functional-Style While pure functional programming isn't fully achieved in Java, developers can adopt functional-style
Java practices by minimizing side effects and using immutable data.

Shared Mutable Mutable data structures can complicate maintenance; promoting immutability enhances clarity and reduces
Data bugs.

Pure Functions Pure functions are free of side effects and produce consistent outputs, simplifying reasoning about code
behavior.

Referential A function is referentially transparent if it can be replaced by its output without changing program
Transparency behavior, aiding understanding and optimization.

Iterative vs. Recursion is fundamental to functional programming, allowing for elegant solutions while avoiding
Recursive mutable state, contrast with iterative constructs that may introduce side effects.
Approaches

Tail Recursion Tail recursion can be optimized by compilers for better performance, though Java lacks native support for
tail call optimization.

Practical A functional style enhances maintainability and clarity; recursion and streams can often replace traditional
Considerations iterations, aiding in navigating modern software complexities.

Summary Reducing shared mutable data improves maintenance. Functional programming emphasizes
side-effect-free methods and declarative styles, with recursion as an efficient alternative to iteration.

Summary of Chapter 20: Thinking Functionally

Scan to Download
Introduction to Functional Programming

This chapter delves into the essence of functional


programming in Java, marked by the emphasis on concepts
such as side effects, immutability, declarative programming,
and referential transparency. The chapter also introduces
functional programming techniques, such as higher-order
functions and combinators.

Concepts of Functional Programming

1.
Why Functional Programming?

Functional programming simplifies maintenance and


debugging by reducing the complexity associated with shared
mutable data. Adopting a functional style promotes clearer
code and enhances modularity.

2.
Defining Functional Programming

Functional programming is characterized by writing


side-effect-free functions akin to mathematical functions.

Scan to Download
Functions should consistently produce the same output for
the same input without altering any state outside their scope.
3.
Declarative Programming

This approach allows programmers to describe what they


want to achieve rather than how to achieve it, leading to
clearer and more concise code structures.
4.
Functional-Style Java

Although pure functional programming isn’t fully


attainable in Java, developers can implement functional-style
techniques by minimizing side effects and focusing on
immutable data.

Key Concepts in Functional Programming

1.
Shared Mutable Data

Mutable data structures complicate maintenance. A clean


approach promotes immutability, enhancing program clarity
and reducing bugs.

Scan to Download
2.
Pure Functions

A pure function does not cause side effects and consistently


returns the same output for the same input. This leads to
easier reasoning about code behavior.
3.
Referential Transparency

A function is referentially transparent if it can be replaced


with its output value without changing the program's
behavior. This principle aids in understanding and optimizing
code.

Iterative vs. Recursive Approaches

1.
Recursion

Recursion serves as a fundamental concept in functional


programming, allowing for elegant problem-solving without
mutable state. It contrasts with iterative constructs like loops,
which can introduce side effects.

Scan to Download
2.
Tail Recursion

While standard recursion consumes more stack space, tail


recursion can be optimized by compilers, facilitating state
reuse and improving performance. However, Java lacks
built-in support for tail call optimization.

Practical Considerations

- Emphasizing functional style can enhance code


maintainability and clarity.
- Options for recursion and streams can replace traditional
iterative approaches in Java programs.
- Adoption of functional programming techniques will assist
developers in navigating the evolving complexities of
modern software systems.

Summary

Reducing shared mutable data structures aids long-term


maintenance. Functional programming favors side-effect-free
methods and encourages declarative programming. Functions
characterized purely by input and output enhance referential

Scan to Download
transparency. Recursion is a viable alternative to iteration,
with tail recursion offering potential optimization
advantages.

Scan to Download
Example
Key Point:Emphasizing Functional Programming
Techniques
Example:Imagine you’re developing a shopping cart
application. Instead of modifying a shared list of
products directly, you create pure functions that derive
new cart states without changing the original data. Each
function consistently produces the same output based on
the current input, allowing for easier debugging and
enhanced clarity in your code.

Scan to Download
Critical Thinking
Key Point:The emphasis on immutability in
functional programming may not universally suit all
programming scenarios.
Critical Interpretation:While functional programming
emphasizes immutability as a means to enhance clarity
and reduce bugs, it is essential to consider the trade-offs.
For instance, the shift from mutable to immutable data
structures can lead to performance overhead in scenarios
requiring high efficiency or memory optimization. Each
programming paradigm has its strengths and
weaknesses, and the suitability of functional
programming principles may vary based on specific
project requirements and constraints. As noted by
Martin Odersky in 'Programming in Scala' (2008), a
balanced approach that leverages both functional and
imperative programming techniques can often yield
better performance and usability outcomes.

Scan to Download
Chapter 21 Summary : 19 Functional
programming techniques

Chapter 21 Summary: Functional Programming


Techniques

Overview

Chapter 21 delves into advanced functional programming


techniques that enhance code maintainability through
concepts such as higher-order functions, currying, persistent
data structures, lazy evaluation, pattern matching, caching,
and combinators.

Key Topics Covered

Functions Everywhere

- Introduces first-class functions and higher-order functions


which can accept functions as arguments, return them as

Scan to Download
results, and can be stored in data structures.
- Java 8 introduced capabilities like method references and
lambda expressions, allowing easier handling of function
values.

Higher-Order Functions

- Defined as functions that either take one or more functions


as parameters or return a function as a result.
- Examples include `Comparator.comparing` and creating
pipelines of operations using functions.

Currying

- A technique to modularize and reuse functions by


transforming a function with multiple arguments into a
sequence of functions each taking a single argument.
- Provides flexibility in creating specialized functions by
pre-filling some parameters.

Persistent Data Structures


Install Bookey App to Unlock Full Text and
Audio
- A key feature in functional programming where data
structures cannot be modified after their creation.

Scan to Download
Chapter 22 Summary : 20 Blending OOP
and FP: Comparing Java and Scala

Summary of Chapter 22: Blending OOP and FP:


Comparing Java and Scala

Introduction to Scala

- Scala merges object-oriented programming (OOP) and


functional programming (FP), positioned as an alternative to
Java.
- It introduces advanced features including a sophisticated
type system, type inference, and pattern matching while
maintaining interoperability with Java libraries.
- The chapter aims to compare Scala and Java,
acknowledging the broader programming ecosystem. It does
not promote Scala as superior but highlights its expressive
capabilities.

Basic Scala Features

Scan to Download
- The chapter opens with a "Hello beer" example in both
imperative and functional styles.
- Scala's syntax allows for concise code and easy collection
manipulation.
- Collections like List, Set, Map, and Tuple can be created
intuitively, with immutability as the default.

Data Structures in Scala

- Collections are immutable by default, favoring persistent


data structures.
- Functional operations such as filter and map are supported,
allowing streamlined collection processing.
- Tuples offer a compact way to group data without needing
to define custom classes, contrasting with Java's more
verbose implementations.

Functions in Scala

- Functions in Scala are first-class citizens, allowing for


flexible handling and passing of functions as arguments.
- Anonymous functions (similar to Java's lambda
expressions) and closures (which can access nonlocal
variables) enhance functional programming capabilities.

Scan to Download
- Currying is natively supported, simplifying the creation of
partially applied functions.

Classes and Traits

- Scala reduces verbosity by automatically generating


constructors, getters, and setters for classes, contrasting
Java's more burdensome syntax.
- Traits in Scala serve a similar purpose to interfaces in Java
but allow for multiple inheritance of states, enabling fields
and default implementations.

Key Takeaways

- Java and Scala share a common JVM foundation, yet Scala


enriches functional programming with more advanced
features.
- Scala's collections and functional capabilities are more
concise and expressive compared to Java, facilitating clearer
and more maintainable code.
- The combination of OOP and FP principles in Scala
provides a robust toolkit for developers seeking a hybrid
programming approach.

Scan to Download
Chapter 23 Summary : 21 Conclusions
and where next for Java

500 Conclusions and Where Next for Java

This chapter summarizes the journey through Java 8 and 9,


emphasizing the evolution towards functional-style
programming, new modularization capabilities in Java 9, and
advancements introduced in Java 10. It also speculates on
future enhancements in Java beyond these versions.

21.1 Review of Java 8 Features

The review of Java 8 features focuses on their


interconnections and how they contribute to a functional
programming style. Key points include:
-
Behavior Parameterization (Lambdas and Method
References)
: Introduces lambdas and method references for more
concise, modular code.

Scan to Download
-
Streams
: The new Streams API allows efficient data processing by
forming operation pipelines, reducing the need for multiple
traversals of large datasets.

-
CompletableFuture
: Enhances multithreading capabilities by allowing
asynchronous programming patterns through methods like
thenCompose and allOf.
-
Optional
: Introduces a type for handling optional values, promoting
safer code and reducing NullPointerExceptions.
-
Flow API
: Java 9's addition for reactive programming standardizes
reactive streams and backpressure protocols.
-
Default Methods
: Allows interfaces to include method implementations,
enabling upward-compatible library extensions.

Scan to Download
21.2 The Java 9 Module System

Java 9 introduces a module system that enhances


architectural design by clearly defining module boundaries.
While it hampers backward compatibility, it also provides:
- Reliable configuration and early error detection.
- Stronger encapsulation for better security.
- Improved performance through optimized module loading.
- Scalability for applications, especially in IoT contexts.

21.3 Java 10 Local Variable Type Inference

Java 10 allows the use of the `var` keyword for inferring


variable types, improving code readability and reducing
boilerplate.

21.4 What’s Ahead for Java?

Looking forward, several enhancements are proposed:


-
Declaration-Site Variance
: A mechanism for specifying variance at the declaration of
generics.

Scan to Download
-
Pattern Matching
: An enhanced way of checking object types that streamlines
conditional logic.

-
Richer Forms of Generics
: Proposals for improving generics to handle more complex
functional types effectively.

-
Deeper Support for Immutability and Value Types
: The introduction of immutable value types to enhance
functional programming practices in Java.

-
Faster Development Cycles
: A shift to a six-month release cadence for Java to stay
relevant and competitive against emerging languages.

21.5 Moving Java Forward Faster

The transition to shorter development cycles is set to allow


newer features and improvements to be incorporated more

Scan to Download
rapidly, with long-term support releases every three years.

21.6 The Final Word

The exploration of Java 8, 9, 10, and beyond reveals


significant evolution towards functional programming,
enhanced modularization, and improved concurrency. The
ongoing trend suggests Java will continue to embrace
functional programming concepts, making it more relevant in
modern software development.

Scan to Download
Example
Key Point:Embracing Functional Programming
Example:Java's evolution towards functional
programming encourages developers like you to
embrace a new coding paradigm that favors brief,
expressive, and modular code through features such as
lambdas and streams. Imagine writing a formation of
data processing using streams where the complex
iterations and manipulations you once handled with
verbose loops have been replaced by concise
expressions. This adventure allows you to focus on
results rather than boilerplate, empowering your coding
skills and enhancing collaboration within teams.

Scan to Download
Chapter 24 Summary : A.1 Annotations

Appendix A: Miscellaneous Language Updates

This appendix discusses three key language updates


introduced in Java 8: repeated annotations, type annotations,
and generalized target-type inference.

A.1 Annotations

Java 8 enhances the annotation mechanism in two significant


ways: allowing repeated annotations and enabling
annotations on any type use. Annotations serve as syntactic
metadata, providing additional information about program
elements. Use cases for annotations include unit tests,
documentation, error detection, and application
configuration.

A.1.1 Repeated Annotations

Prior to Java 8, Java’s annotation system restricted multiple


annotations of the same type on a declaration. To work
around this, programmers often created container

Scan to Download
annotations. Java 8 now allows you to specify repeatable
annotations directly using the `@Repeatable` annotation,
simplifying previous practices.
To make an annotation repeatable:
1. Mark the annotation with `@Repeatable`.
2. Provide a container annotation.
For example:
```java
@Repeatable(Authors.class)
@interface Author { String name(); }
@interface Authors { Author[] value(); }
```
This allows direct annotation like:
```java
@Author(name="Raoul") @Author(name="Mario")
@Author(name="Alan") class Book{}
```
The class can then retrieve multiple annotations using the
new `getAnnotationsByType` method.

A.1.2 Type Annotations


Install Bookey App to Unlock Full Text and
Audio
Java 8 extends the applicability of annotations to any type
use, including variables, type casts, and generics. For

Scan to Download
Chapter 25 Summary : A.2 Generalized
target-type inference

Chapter 25 Summary: Miscellaneous Language


Updates

Annotations in Java 8

Java 8 does not come with built-in annotations or tools, but


the Checker framework allows users to define type
annotations and enhance type checking. More details and
tutorial resources are available at the Checker framework
website.

Generalized Target-Type Inference

Java 8 improves inference of generic arguments, enabling


more intuitive type handling. Prior to Java 8, explicit type
declarations were often necessary, especially when calling
methods like emptyList. The target type inference
mechanism in Java 8 allows for cleaner code by inferring

Scan to Download
types directly from method arguments without explicit
declarations. For example, the method cleanCars can now
accept collections created by Collections.emptyList() without
requiring extra type arguments, streamlining the process of
working with generics.

Scan to Download
Chapter 26 Summary : B.1 Collections

Appendix B: Miscellaneous Library Updates

B.1 Collections Overview

- Java 8 introduced significant updates to the Collections


API, particularly with the addition of streams.
- Other updates and new methods are discussed in various
chapters and summarized here.

B.1.1 Additional Methods

- Default methods were added to collection interfaces and


classes. Key new methods include:
| Class/Interface | New Methods |
|------------------|-------------|
| Map | getOrDefault, forEach, compute,
computeIfAbsent, computeIfPresent, merge, putIfAbsent,
remove(key, value), replace, replaceAll, of, ofEntries |
| Iterable | forEach, spliterator |
| Iterator | forEachRemaining |

Scan to Download
| Collection | removeIf, stream, parallelStream |
| List | replaceAll, sort, of |
| BitSet | stream |
| Set | of |

B.1.2 Map Interface Enhancements

- The Map interface saw significant updates with convenient


methods like:
-
getOrDefault
: Simplifies retrieval with a default value if the key is absent.
- Example usage: `Integer count =
map.getOrDefault("Aston Martin", 0);`
-
computeIfAbsent
: Helps implement caching patterns concisely.
- Example improved usage: `return
cache.computeIfAbsent(url, this::getData);`
- Additional methods were also introduced in
ConcurrentHashMap.

B.1.3 Collection Interface Enhancements

Scan to Download
- The
removeIf
method enables removal of elements matching a predicate
from a collection.

B.1.4 List Interface Enhancements

- The
replaceAll
method mutates elements in a List based on a given
operator.
- Example: `numbers.replaceAll(x -> x * 2);` modifies the
list in place.

B.1.5 Collections Class Updates

- Adds methods for returning unmodifiable, synchronized,


checked, and empty NavigableMap and NavigableSet.
- Introduces
checkedQueue
for dynamic type checking in Queues.

B.1.6 Comparator Interface Enhancements

Scan to Download
- The Comparator interface now features both default and
static methods, including:
-
New instance methods
:
- `reversed`, `thenComparing`, `thenComparingInt`, etc.
-
New static methods
:
- `comparingInt`, `naturalOrder`, `nullsFirst`,
`reverseOrder`, etc.

Scan to Download
Chapter 27 Summary : B.2 Concurrency

Chapter 27 Summary: Concurrency Updates in


Java 8

Introduction to Concurrency Updates

Java 8 introduces significant updates in concurrency,


including the addition of parallel streams and the
CompletableFuture class, as well as enhancements in the
atomic variable management and ConcurrentHashMap
functionalities.

Atomic Updates

- The `java.util.concurrent.atomic` package introduces


several numeric atomic classes such as `AtomicInteger` and
`AtomicLong`.
- New methods added:
-
getAndUpdate
: Updates the current value based on a function and returns

Scan to Download
the previous value.
-
updateAndGet
: Updates the current value and returns the updated value.
-
getAndAccumulate
: Updates the value with a function applied to the current and
given values, returning the previous value.
-
accumulateAndGet
: Similar to the above but returns the updated value.
- Recommendation to use `LongAdder`, `LongAccumulator`,
`DoubleAdder`, and `DoubleAccumulator` for scenarios with
frequent updates by multiple threads, as they help reduce
contention.

Example of Atomic Operations

- Using `LongAdder`:
```java
LongAdder adder = new LongAdder();
Install Bookey App to Unlock
adder.add(10); Full Text and
long sum = adder.sum(); Audio
```

Scan to Download
Chapter 28 Summary : B.3 Arrays

Chapter 28 Summary: Miscellaneous Library


Updates

ConcurrentHashMap Enhancements

-
Parallel Reduction
: The `reduceValues` method allows finding maximum values
with varying levels of parallelism based on input thresholds.
Using a value of 1 enables maximum parallelism, while
`Long.MAX_VALUE` restricts operations to a single thread.
-
Count of Mappings
: The new `mappingCount` method in `ConcurrentHashMap`
returns the number of mappings as a long, superseding the
`size` method which returns an int, important for larger
mappings.
-
Set Views
: The `keySet` method provides a dynamic view of the map

Scan to Download
as a Set, and `newKeySet` allows creating a Set backed by
`ConcurrentHashMap`.

Array Manipulation Updates

-
Parallel Sorting
: New `parallelSort` method sorts arrays in parallel, based on
natural order or a specified Comparator.
-
Array Element Setting
: The methods `setAll` and `parallelSetAll` set all elements of
an array sequentially or in parallel, respectively, leveraging a
provided function. This requires the function to be
side-effect-free when using `parallelSetAll`. For example,
`Arrays.setAll` can initialize an array with even numbers.

Scan to Download
Chapter 29 Summary : B.4 Number and
Math

Using parallelPrefix

The `parallelPrefix` method allows for the parallel


accumulation of array elements using a specified binary
operator. For example, creating an array filled with ones and
applying `parallelPrefix` can yield cumulative results,
transforming an array of ten elements from `1` to `10`.

Number and Math Enhancements in Java 8

Number Class Enhancements

-
Static Methods
: The `Short`, `Integer`, `Long`, `Float`, and `Double` classes
now feature static methods for `sum`, `min`, and `max`.
-
Unsigned Operations

Scan to Download
: `Integer` and `Long` have methods such as
`compareUnsigned`, `divideUnsigned`,
`remainderUnsigned`, and `toUnsignedString`. They also
include parsing methods: `parseUnsignedInt` and
`parseUnsignedLong`.
-
Conversion Methods
: `Byte` and `Short` can now convert to unsigned `int` or
`long`, with `Integer` also capable of converting to an
unsigned `long`.
-
Floating-Point Check
: `Double` and `Float` have a method `isFinite` to check if a
value is finite.
-
Boolean Operations
: The `Boolean` class now includes `logicalAnd`, `logicalOr`,
and `logicalXor` for boolean operations.
-
BigInteger Conversions
: Methods like `byteValueExact`, `shortValueExact`,
`intValueExact`, and `longValueExact` convert a `BigInteger`
to a primitive type, throwing an exception if there's a loss of
information.

Scan to Download
Math Class Enhancements

-
Exact Operations
: The `Math` class introduces methods like `addExact`,
`subtractExact`, `multiplyExact`, as well as
`incrementExact`, `decrementExact`, and `negateExact`
which throw exceptions for overflow in `int` and `long`
calculations.
-
Additional Methods
: New static methods such as `floorMod`, `floorDiv`, and
`nextDown` have also been added to enhance functionality.

Scan to Download
Chapter 30 Summary : B.7 String

Chapter 30 Summary: Miscellaneous Library


Updates

Files Enhancements

Recent additions to the Files class allow the production of


streams from files. Key methods include:
-
Files.lines
: Reads a file as a stream lazily.
-
Files.list
: Produces a non-recursive Stream<Path> of directory entries,
which is efficient for processing large directories.
-
Files.walk
: Similar to list, but provides a recursive Stream<Path> with
configurable depth, using depth-first traversal.
-
Files.find

Scan to Download
: Recursively traverses a directory to generate a
Stream<Path> of entries that match a specified predicate.

Reflection API Updates

The Reflection API has been updated to accommodate


changes made to the annotation mechanism in Java 8. A
notable addition is the
java.lang.reflect.Parameter
class, which allows access to method parameter information
including names and modifiers. This class is part of the new
java.lang.reflect.Executable
superclass that unifies functionality for Method and
Constructor.

String Class Improvements

The String class has introduced a new static method called


join
, which facilitates joining strings with a specified delimiter.
Example usage:
```java
String authors = String.join(", ", "Raoul", "Mario", "Alan");
System.out.println(authors); // Output: Raoul, Mario, Alan
```

Scan to Download
Chapter 31 Summary : C.1 Forking a
stream

Chapter 31 Summary: Performing Multiple


Operations in Parallel on a Stream

C.1 Forking a Stream

To execute multiple operations in parallel on a stream, a


`StreamForker` class is created, which wraps the original
stream and allows the user to define different operations. The
key points include:
- The `fork` method accepts a key and a function to transform
the stream, storing these in a map for future retrieval.
- The execution of all operations is triggered by calling the
`getResults` method, which implements the `Results`
interface, allowing results to be retrieved using the
corresponding keys.

C.1.1 Implementing the Results Interface with the


ForkingStreamConsumer

Scan to Download
The `getResults` implementation utilizes a
`ForkingStreamConsumer`, responsible for processing the
stream elements and distributing them across multiple
blocking queues based on the operations defined. This
ensures that the stream remains sequential to avoid issues
with order.

C.1.2 Developing ForkingStreamConsumer and


BlockingQueueSpliterator

- The `ForkingStreamConsumer` class implements both


`Consumer` and `Results` interfaces, adding each stream
element to all queues.
- After processing, it adds a special end-of-stream marker to
signal completion.
- The `BlockingQueueSpliterator` serves as a late-binding
spliterator, which retrieves elements from a blocking queue
and processes them accordingly.

C.1.3 Putting the StreamForker to Work

An example is provided using the `StreamForker` with a


menu data model to perform various operations in parallel,

Scan to Download
such as:
- Creating a comma-separated list of dish names
- Calculating total calories
- Finding the dish with the most calories
- Grouping dishes by their type
The results are retrieved using the keys defined during the
forking process, showcasing the effectiveness and
convenience of the `StreamForker`'s fluent API. The example
code illustrates how to initiate the fork, define operations,
and obtain results.
This chapter highlights the `StreamForker` as an efficient
tool for parallel stream processing, leveraging Java's
functional features.

Scan to Download
Chapter 32 Summary : D.1 Anonymous
classes

Appendix D: Lambdas and JVM Bytecode

This appendix explores the implementation of lambda


expressions in Java and how the JVM handles them.

D.1: Anonymous Classes

Lambda expressions can be compared to anonymous classes,


as both can implement functional interfaces. However,
translating lambda expressions to anonymous classes
presents performance issues:
-
Class File Generation
: Each anonymous class results in a new class file (e.g.,
ClassName$1), leading to an increased number of class files
to load and verify, which can degrade application startup
performance.
-
Subtype Creation

Scan to Download
: Every new anonymous class creates a distinct subtype,
leading to inefficient management if numerous lambda
expressions are used.
Thus, translating lambda expressions into anonymous classes
is not optimal for performance.

Scan to Download
Chapter 33 Summary : D.2 Bytecode
generation

Summary of Chapter 33: Bytecode Generation in


Java

Introduction to Bytecode Generation

Bytecode generation can result in various subtypes of


Comparator, potentially complicating performance
optimizations by the JVM.

Compilation Process

A Java source file is compiled into bytecode by the Java


compiler, which the JVM then executes. Differences in
bytecode instructions arise from the use of anonymous
classes and lambda expressions.

Inspecting Bytecode

Scan to Download
The bytecode and constant pool of any class can be examined
using the command:
```
javap -c -v ClassName
```

Example Implementation

A Function interface instance can be created using the Java 7


syntax with an anonymous inner class, as demonstrated in the
provided code listing.

Generated Bytecode

The bytecode generated for the anonymous inner class is


explained with an accompanying breakdown of the
operations:
- Instantiation of InnerClass$1 with `new`.
- Duplication of the reference on the stack using `dup`.
- Initialization of the object with `invokespecial`.
- The reference is stored in the field `f` of the InnerClass
Install
using Bookey App to Unlock Full Text and
`putfield`.
Audio
Conclusion

Scan to Download
Chapter 34 Summary : D.3
Invokedynamic to the rescue

Summary of Chapter 34: Lambdas and JVM


Bytecode

Anonymous Classes and Compiled Bytecode

- The compiler generates an anonymous class named


`InnerClass$1` for implementations of the `Function`
interface.
- Example implementation shows how the function is
structured:
- `class InnerClass$1 implements
java.util.function.Function<java.lang.Object,
java.lang.String> { ... }`
- The bytecode instructions provide insight into how the
method operates.

Lambda Expressions in Java 8

Scan to Download
- Java 8 introduces lambda expressions, allowing for cleaner
and more concise code.
- A lambda expression example:
- `Function<Object, String> f = obj -> obj.toString();`
- The corresponding bytecode demonstrates how lambda
expressions simplify the structure by eliminating the need for
an extra class:
- Uses the `invokedynamic` instruction instead of creating
new class files.

The Role of invokedynamic

- Introduced in JDK7, `invokedynamic` provides support for


dynamically typed languages on the JVM.
- It allows for a higher level of indirection in method
invocation.
- This is particularly useful for scenarios where types are not
known at compile time, enabling flexible method calls that
adapt to different data types at runtime.

Scan to Download
Chapter 35 Summary : D.4
Code-generation strategies

Code-Generation Strategies for Lambda


Expressions

Introduction to Invokedynamic Instruction

The invokedynamic instruction is utilized in a novel manner


to delay the translation of lambda expressions into bytecode
until runtime. This allows for:
- Code generation strategy to be an implementation detail,
enabling future optimizations while maintaining backward
compatibility.
- No performance overhead when a lambda is unused.
- Caching of stateless lambdas for efficiency, optimizing
common cases.
- On first invocation, runtime translation occurs, while
subsequent calls leverage prelinked implementations.

Lambda Expression Translation

Scan to Download
Lambda expressions are translated into bytecode by
encapsulating their body within a static method created at
runtime. The simplest form, stateless lambdas, allows for
straightforward method generation:
```java
public class Lambda {
Function<Object, String> f = [dynamic invocation of
lambda$1];
static String lambda$1(Object obj) { return obj.toString();
}
}
```

Bootstrap Method and Call Site

A bootstrap method dictates the actual method to call,


facilitating efficient method resolution. Once the method is
identified (e.g., for repeated calls with the same parameters),
it can be retrieved from the call site without further lookup.

Handling Captured Variables in Lambdas

For lambdas that capture local variables or fields, the

Scan to Download
signature of the generated method requires modification to
include extra arguments that represent the captured context.
This leads to a structure resembling:
```java
public class Lambda {
String header = "This is a ";
Function<Object, String> f = [dynamic invocation of
lambda$1];
static String lambda$1(String header, Object obj) { return
header + obj.toString(); }
}
```

Further Information

For a deeper understanding of the lambda translation process,


refer to the provided link:
[Lambda Translation Process](http://cr.openjdk.java.net/~bri
angoetz/lambda/lambda-translation.html)

Scan to Download
Chapter 36 Summary : A

Chapter 36 Summary

Index of Key Symbols and Methods

-
Symbols
:
- :: operator - 461
- ? wildcard - 144
- _ (underscore) character - 491
- -> (arrow) - 44
- <> (diamond) operator - 61, 223
-
Important Classes and Methods
:
- Abstract classes - 321
- Abstract methods - 47
- Accept method - 533
- AccumulateAndGet method - 524
- Accumulator method - 160, 168

Scan to Download
- AddExact method - 527
- AllOf method - 413

Alternative Calendar Systems

- Overview of alternative calendar systems - 311–313

Asynchronous Programming

- Overview:
- Asynchronous API - 390
- CompletableFutures - 390
- Futures - 388–390
- Comparison: CompletableFutures vs. others - 409–410
- Implementing Asynchronous APIs:
- Converting synchronous methods - 392–393
- Error handling - 394–395
- Nonblocking code - 396–402
- Custom Executor - 400–402
- Strategies for scaling solutions - 399–400
- Pipelining asynchronous tasks - 402–411
Install Bookey
- Combining Tasks: App to Unlock Full Text and
Audio - 408-409
- Composing CompletableFutures
- Combining synchronous and asynchronous operations -

Scan to Download
Chapter 37 Summary : C

Chapter 37 Summary: Modern Java in Action

Index Highlights

This chapter provides an extensive index covering various


topics related to Java programming, particularly
enhancements in the Java Collections Framework, functional
programming concepts, and concurrency.

Key Concepts

-
Atomic Package & Concurrency
: Discusses atomic operations and concurrent data structures
enhancing thread safety and performance.
-
Behavior-Driven Development (BDD)
: Introduces BDD principles along with features like the
@Before annotation.
-

Scan to Download
Lambdas and Functional Interfaces
: Covers lambda expressions, functional interfaces (e.g.,
BiFunction), and behaviors such as filtering and sorting.
-
Collectors API
: Explains how to collect and manipulate data with collectors,
including predefined collectors like summingInt and
groupingBy.
-
CompletableFutures
: Details on asynchronous programming, including methods
to create and manage Future tasks and handle their results.

Advanced Topics

-
Callbacks and Closures
: Examines the use of closures in lambda expressions and
strategies for implementing callbacks.
-
Behavioural Compatibility
: Discusses the importance of maintaining compatibility in
interfaces and implementations as systems evolve.
-

Scan to Download
Reactive Programming
: Introduces the concepts of reactive programming and its
relation to Java concurrency, including backpressure
mechanisms.

Conclusion

Overall, this chapter acts as a comprehensive guide to


understanding various advanced Java programming concepts
and tools for both concurrency and functional programming.
It serves programmers seeking to enhance their knowledge of
modern practices and frameworks within Java.

Scan to Download
Chapter 38 Summary : D

Summary of Chapter 38: Key Concepts and


Components

ConcurrentHashMap

- Overview of class functionality and performance


- Key methods: counting, keySet, mappingCount
- Operations: reduce, search, and stream-like capabilities
- Performance insights and handling
ConcurrentModificationException

Data Processing with Fork/Join Framework

- Overview of data processing metrics and best practices


- Utilizing RecursiveTask class and work-stealing principles
- Detailed performance measurement methods
- Transitioning from sequential to parallel streams and
employing specialized methods

Date and Time API

Scan to Download
- Key classes: Duration, Instant, LocalDate, LocalTime, and
Period
- Functions for manipulating, printing, and parsing date-time
objects
- Managing time zones and alternative calendar systems

Default Methods in Interfaces

- Purpose and benefits of default methods in evolving APIs


- Overview of resolution rules and conflict handling
- Concepts related to multiple inheritance of behavior and
usage patterns

Declarative Programming and Design Patterns

- Introduction to the principles of declarative programming


- Summary of design patterns and their application in modern
Java

Domain-Specific Languages (DSLs)

- Techniques for creating DSLs: function sequencing,


method chaining, and nested functions

Scan to Download
- Real-world examples and applications of DSLs
- Evaluating the pros and cons of DSL implementations
This summary encapsulates the essential topics covered in
Chapter 38, providing a concise understanding of modern
Java's capabilities and best practices.

Scan to Download
Chapter 39 Summary : F

Chapter 39 Summary

Overview of Domain-Specific Languages (DSLs)

- DSLs on JVM: Discusses external (247-248) and internal


DSLs (244-245), as well as polyglot DSLs (245-247).

Error Handling and Functional Programming


Constructs

- Use of method references (263-266) and handling empty


Optionals (281).
- Through exceptional program flows, the exceptionally
method (372) can be utilized.

Concurrency and Threads Management

- Executor framework: Custom Executors (400-402) and the


ExecutorService interface (40).
- Fork/Join framework (184-190): Best practices for

Scan to Download
implementation, including tasks like ForkJoinSumCalculator
(187-188) and work-stealing (189-190).

Data Handling Techniques

- File handling operations using classes like File (13),


FileFilter (13), and Files (528) for building streams
(127-128).
- Various filtering methods available (15, 30, 46) for handling
collections and data (filter method, rejecting values:
290-291).

Stream Operations and Lambda Expressions

- The chapter emphasizes the use of filtering (27-35),


particularly through lambda expressions (37-38) and the filter
method (30).
- The usage of flatMap (104, 106) and forEach (54, 181)
methods for efficiently processing data streams.

Mathematical Functions and Patterns


Install Bookey App to Unlock Full Text and
Audio
- Covers recursive functions such as factorialHelper (457)
and factorialRecursive (457).

Scan to Download
Chapter 40 Summary : I

Chapter 40 Summary: Key Concepts and Functions


in Modern Java

Function Descriptors and Interfaces

- Function descriptors and functional interfaces are crucial in


understanding functional programming in Java.
- Key interfaces include Consumer, Function, and Predicate,
which facilitate expressing operations in lambda form and
enable patterns like execute-around.

Functional Programming Concepts

- Emphasizes aspects such as caching (memoization),


currying, lazy evaluation, and persistent data structures.
- Differences between object-oriented and functional
programming styles are highlighted, including the benefits of
higher-order functions and referential transparency.
- Introduces techniques like pattern matching and recursion
vs. iteration.

Scan to Download
Lambda Expressions and Streams

- Explains the use of lambda expressions, closures, and


anonymous functions as first-class citizens.
- Discusses building and manipulating streams, including
creating lazy lists and self-defining streams.

Java Generics

- Covers generics in function types, reified generics, and


additional syntactic flexibility.
- Touches on primitive specializations and their relevance in
functional programming contexts.

Grouping and Collecting Data

- Discusses methods for grouping data, manipulating grouped


elements, and collecting data in subgroups.
- Includes multilevel grouping strategies and corresponding
methods like groupingBy.

I/O and Concurrency

Scan to Download
- Briefly mentions future-style APIs and
CompletableFutures, alongside their limits and advantages
for handling asynchronous tasks.
- Describes various methods related to data processing, such
as get, hashcode, and aggregation functions.
This chapter serves as a comprehensive overview of
functional programming principles applied in Java,
showcasing tools and methodologies developers can leverage
for effective, efficient coding in modern applications.

Scan to Download
Example
Key Point:Understanding Functional Interfaces in
Java
Example:Imagine you are building an application that
processes user input to generate responses. By utilizing
functional interfaces like Function and Consumer, you
can effortlessly handle input transformations and output
actions using concise lambda expressions. For instance,
instead of creating a verbose class to define input
handling logic, you can elegantly define a lambda that
processes the input directly, demonstrating the power of
functional programming in reducing boilerplate code
and increasing readability.

Scan to Download
Chapter 41 Summary : J

INDEX SUMMARY

Key Topics:

1.
Java & Development:

-
Java Enhancements:
Overview of Java changes (3-5), default methods (21-22),
and future plans (507-514).
-
JDK and Java Module System:
JDK outline (337-338), Java module system details
(333-353).
-
Java Archive (JAR):
Purpose and usage of JAR files (176).
2.
Programming Concepts:

Scan to Download
-
Streams and Operations:
Infinite streams (128-132), internal iteration (18, 86, 448),
and intermediate operations (94-95).
-
Lambda Expressions:
Role and importance (12-17).
-
Behavior Parameterization:
Exploring design and method usage (9-10).
3.
IoT and Reactive Programming:

-
Internet of Things (IoT):
Its significance and applications (417, 505).
-
Reactive Programming:
Classes like Flowable and Observable exploring
asynchronous data (432).
4.
Language Features:

Scan to Download
-
Interfaces and Inheritance:
Understanding fundamental principles (316, 326).
-
Pattern Matching and Value Types:
Current trends and future functionalities in Java (507-508,
511-514).
-
Generics and Immutability:
Coverage of generics changes and immutability support
(508-510, 510-511).
5.
Error Handling and Validation:

-
Common Classes:
IOException handling (51) and utility classes such as
IntSummaryStatistics (140).
-
Validation Methods:
Overview of methods like isPresent and isValidName (66,
289).
6.
Miscellaneous Topics:

Scan to Download
-
Internal DSLs:
Exploring domain-specific languages (241, 244-245).
-
Concurrency:
Java's concurrency utilities and their usage (425).
-
Mathematical Functions:
Coverage of functional interfaces (IntPredicate,
IntUnaryOperator) and methods (isPrime, iterative factorial).

Conclusion:

The chapter encompasses various advanced Java concepts


and trends, including the evolution of the language, the
significance of modularity, the integration of reactive
programming, and error handling methodologies.
Understanding these topics is crucial for modern Java
development and application design.

Scan to Download
Chapter 42 Summary : L

Summary of Chapter 42: Key Concepts and


References

Introduction to Java Utilities

- The chapter discusses various classes and interfaces


available in the `java.util` package, focusing on utilities for
concurrency, functional programming, and stream
processing.

Concurrency Utilities

-
java.util.concurrent Package
: This section covers important classes such as `Future`,
`ForkJoinPool`, and constructs for parallel computations.
-
Flow Class
: Explores reactive programming with the `Flow` class and
its relevance in asynchronous programming.

Scan to Download
Functional Programming in Java

-
Functional Interfaces
: Describes key interfaces like `Consumer`, `Function`, and
`Predicate`. These interfaces enable behavior
parameterization and higher-order functions.
-
Lambda Expressions
: Presents the syntax, usage, and benefits of lambda
expressions, emphasizing their role in creating concise and
readable code.

Java Streams

-
Stream API
: Discusses the `Stream` class and its capabilities in handling
collections of data through functional-style operations.

Install
Design Bookey
Patterns App to Unlock
and Refactoring Full Text and
Audio
-

Scan to Download
Chapter 43 Summary : N

Summary of Chapter 43: Modern Java in Action

Key Concepts and Methods:

-
Logical Operations:

- `logicalOr` and `logicalXor` methods (527) are explored.


-
Concurrency:

- `LongAccumulator` and `LongAdder` classes (524)


enhance performance in concurrent applications.
- Practical usage of the `newFixedThreadPool` method
(363) is discussed.
-
Mapping and Collections:

- The chapter introduces various Map factories (204–205)


and methods, including `compute` patterns, `forEach`, and

Scan to Download
sorting capabilities.
- The `mapping` streams utilize functions to apply changes
to each element, emphasizing the use of `map`, `flatMap`,
and `Arrays.stream`.
-
Java's Math Functionalities:

- An overview of the Math class (527) and mathematical


functions available to simplify calculations.
-
Methods and Functional Programming:

- An in-depth analysis of method references (13, 64–70),


including their construction, types, and practical applications
in different programming paradigms like DSLs.
-
Performance Optimization:

- Introduction to microbenchmarks (176) for assessing


performance improvements in Java code.
-
Modularity and Code Structure:

- Discussion on modules (21–22), their descriptors, and the

Scan to Download
importance of creating modular code for scalability.
-
Error Handling:

- Managing exceptions with `NoSuchElementException`


and its implications in code execution (110, 288).

Programming Practices:

-
Memoization:

- Techniques for caching results in functions, promoting


efficiency (452).
-
Method Chaining and Behavior Parameterization:

- The concept of chaining methods for cleaner code and the


passing of code for flexible behavior adjustment (255–257).

Data Structures:

Scan to Download
Linked Lists and Custom Utility Classes:

- Introduction to custom data structures like


`MyLinkedList` (473) and utility classes such as
`MyMathsUtils` (14).
This chapter provides a comprehensive overview of modern
Java practices, emphasizing functional programming,
concurrency, modular structure, and practical usage of
collections and maps.

Scan to Download
Chapter 44 Summary : P
Section Summary

Null Values and Discusses alternatives to null, emphasizing the avoidance of null references and utilizing Optionals to
Alternatives manage potentially null values.

Use of Optionals Introduces the Optional class to model value absence, detailing methods like `Optional.empty`,
`Optional.ofNullable`, and `OptionalInt`, along with practical examples.

Object Reference and Covers object-oriented design patterns such as chain of responsibility and strategy, highlighting their
Design Patterns role in code organization, scalability, and maintainability.

Object-Relational Provides an overview of ORM, explaining how objects are mapped to database tables.
Mapping (ORM)

Parallel Data Discusses efficient parallel data processing via parallel streams and the fork/join framework,
Processing including best practices for performance measurement and optimization.

Practical Applications Concludes with practical applications that showcase the theoretical concepts, demonstrating their use
and Examples in real-world scenarios.

Summary of Chapter 44

Null Values and Alternatives

- Alternatives to null in other languages are discussed,


emphasizing the need to avoid null references.
- Key techniques include using Optionals to wrap potentially
null values and highlighting problems associated with null.

Use of Optionals

Scan to Download
- The Optional class is introduced as a way to model the
absence of a value.
- Various methods of the Optional class, such as
`Optional.empty`, `Optional.ofNullable`, and `OptionalInt`,
are outlined.
- Practical examples of creating, manipulating, and
transforming Optionals, including filtering and combining,
are provided.

Object Reference and Design Patterns

- Object-oriented design patterns are covered, including


patterns like chain of responsibility, factory, observer,
strategy, and template method.
- The importance of design patterns in organizing code and
improving scalability and maintainability is emphasized.

Object-Relational Mapping (ORM)

- An overview of ORM concepts is presented, providing


insight into how objects are mapped to database tables.

Parallel Data Processing

Scan to Download
- Techniques for efficient parallel data processing using
parallel streams and the fork/join framework are discussed.
- Best practices for measuring performance and optimizing
parallel processing are shared, alongside the use of the
Spliterator interface for data splitting.

Practical Applications and Examples

- The chapter concludes with practical applications and


examples that illustrate the theoretical concepts in action,
demonstrating their utility in real-world situations.

Scan to Download
Chapter 45 Summary : R

Chapter 45 Summary

Index of Key Topics

-
Parallel Method
: Describes methods and operations for parallel processing
including measurements and performance considerations.
-
Parallel Streams
: Focuses on how to convert, measure, and effectively utilize
parallel streams while discussing performance trade-offs.
-
Partitioning
: Discusses the advantages of partitioning data, particularly in
the context of prime number collections.
-
Predicate Interface
: Covers the use of predicates in filtering and slicing streams.
-

Scan to Download
Primitive Specializations
: Highlights the conversion processes and mapping to
numeric streams.
-
Publish-Subscribe Model
: Explains the publisher-subscriber interaction and protocols
in reactive programming.
-
Reactive Programming
: Defines concepts of reactive systems, including
backpressure and the Flow API.

Detailed Sections

-
Parallel Operations
:
Explains the introduction and performance aspects of
parallel operations. Techniques include measuring
performance, transforming sequential streams, and effective
usage of specialized methods.
- Install Bookey App to Unlock Full Text and
Partitioning Techniques Audio
:

Scan to Download
Chapter 46 Summary : S

INDEX Summary

Reactive Programming

-
RxJava Reactive Library

- Creating and using Observables (431-437)


- Transforming and combining Observables (437-440)
- Real backpressure fundamentals (384-385)
- Summing two flows (383-384)
- Reactive pull-based backpressure (385)
- Reactive streams overview (421-431)
- Creating reactive applications (424-429)
- Flow class details (421-424)
- Data transformation with Processor (429-431)

Refactoring Techniques

- For improved flexibility (221-223)

Scan to Download
- Adopting functional interfaces (221)
- Enhancing readability (217-223)

Object-Oriented Design Patterns

- Chain of Responsibility (229)


- Factory Pattern (230-232)
- Observer Pattern (226-229)
- Strategy Pattern (224)
- Template Method Pattern (225-226)

Streams Overview

-
Creating Streams

- From arrays and files (127-128)


- From functions (128-132)
- From values and nullable types (126-127)
-
Stream Operations

- Filtering, finding, grouping, and mapping elements


(99-110, 146-154)

Scan to Download
- Performance considerations and advanced reductions
(136-171)

Scala Programming

- Classes, functions, and collections (485-499)


- Functional vs. Imperative styles (486-488)
- Handling Option data structures and streams (492-493)
This summary encapsulates the major topics discussed in
Chapter 46, providing an organized overview of reactive
programming concepts, refactoring techniques, design
patterns, streams operations, and Scala programming basics.

Scan to Download
Chapter 47 Summary : T

Summary of Chapter 47: Index Overview

Streams

-
Numeric
: Ranges, operations, and specializations.
-
Parallel
: Concepts, performance measurement, and effective usage.
-
Reactive
: Creating applications, Flow class, and data transformation.

Reduction

-
Generalized Summarization
: Techniques for finding maximum/minimum, string joining,
and overall summarization.

Scan to Download
Stream Manipulation

-
Slicing and Skipping
: Techniques for element handling, including use of
predicates and truncating.

Design Patterns

-
Visitor and Template
: Overview of structural patterns and their implementation.

Concurrency and Threads

-
Thread Management
: Executor usage, thread pool advantages/disadvantages, and
higher-level abstractions.

Methods and Utilities

Scan to Download
Various Methods
: Includes summarization methods, APIs, and specific
functional utilities.

Miscellaneous

-
Syntactic Metadata
: Target typing and inference in Java.

Scan to Download
Chapter 48 Summary : Z

Summary of Chapter 48 from "Modern Java in


Action"

Introduction

Chapter 48 presents a comprehensive index of concepts,


methods, classes, and keywords related to modern Java
programming.

Key Concepts and Terms

-
Collections and Streams
: Includes details on methods like `toListCollector`, `toSet`,
and various stream operations such as `truncating streams`
and `UNORDERED operation`.
-
Functional Programming
: Discusses lambda expressions, functional interfaces like
`TriFunction`, and visitor design patterns.

Scan to Download
-
Concurrency
: Highlights concepts such as worker threads, work stealing,
and w/C (wait/compute) ratios.

Advanced Java Features

-
Java 9 and Beyond
: Introduces new features and enhancements in recent Java
versions, particularly focusing on the Java Module System.
-
Annotations and Type Checking
: Covers type annotations, type inference, and unboxing.

Programming Techniques

-
Building Streams
: Offers insights into creating streams from values and unique
character handling.
- Install Bookey App to Unlock Full Text and
Error Handling Audio
: Lists several exceptions like

Scan to Download
Best Quotes from Modern Java in Action
by Raoul-Gabriel Urma with Page
Numbers
View on Bookey Website and Generate Beautiful Quote Images

Chapter 1 | Quotes From Pages 25-27


1.Streams—what are they?” They’re a great new
Java 8 addition.
2.First, if you’ve ever programmed using a database-query
language such as SQL, you’ll recognize that it enables
queries to be written in a few lines that would take many
lines in Java.
3.What’s great about Java 8 is that it incorporates many of
the best ideas from functional programming into the
familiar Java syntax.
4.Think of it as having a wider range of weapons in your
programming armory.
5.By the end of this first part, you’ll have a full
understanding of what lambda expressions are, and you’ll
be able to write code that’s both concise and flexible

Scan to Download
enough to easily adapt to changing requirements.
6.It covers using collection factories and learning new
idiomatic patterns to work with List and Set collections
along with idiomatic patterns involving Map.
Chapter 2 | Quotes From Pages 28-28
1.Manning’s commitment to our readers is to
provide a venue where a meaningful dialogue
between individual readers and between readers
and the authors can take place.
2.In chapter 21, we review the journey of learning about Java
8 and the gentle push toward functional-style
programming.
3.All source code in listings or in text is in a fixed-width font
like this to separate it from ordinary text.
4.Both links to the source code may be found at
www.manning.com/books/modern-java-in-action.
5.To access the forum, go to
https://forums.manning.com/forums/modern-java-in-action.
Chapter 3 | Quotes From Pages -58

Scan to Download
1.Java has won a large following of students, project
managers, and programmers who are active users.
It’s an expressive language and continues to be
used for projects both large and small.
2.The good news is that the changes enable you to write
programs more easily.
3.Java has followed an evolutionary path of continually
trying to make concurrency easier and less error-prone.
4....there’s a danger that the Java Virtual Machine (JVM) and
its bytecode will be seen as more important than the Java
language itself.
5.Java 8 provides a new API (called Streams) that supports
many parallel operations to process data and resembles the
way you might think in database query languages.
6.You must provide behavior that is safe to execute
concurrently on different pieces of the input. Typically this
means writing code that doesn’t access shared mutable data
to do its job.
7.Languages need to evolve to track changing hardware or

Scan to Download
programmer expectations.
8.The main changes in Java 8 reflect a move away from
classical object orientation, which often focuses on
mutating existing values, and toward the functional-style
programming spectrum.
9....the new Java 8 features might, in the ecosystem analogy,
enable Java to conquer programming-task territory
currently occupied by other languages.

Scan to Download
Chapter 4 | Quotes From Pages 59-74
1.Behavior parameterization is a software
development pattern that lets you handle frequent
requirement changes.
2.A good principle is this: when you find yourself writing
nearly repeated code, try to abstract instead.
3.This code is much more flexible than our first attempt, but
at the same time it’s easy to read and to use!
4.You’ve achieved something cool; the behavior of the
filterApples method depends on the code you pass to it via
the ApplePredicate object.
5.Isn’t it cool? You’ve managed to find the sweet spot
between flexibility and conciseness, which wasn’t possible
prior to Java 8!
Chapter 5 | Quotes From Pages 75-111
1.Lambda expressions let you pass code concisely.
2.A functional interface is an interface that declares exactly
one abstract method.
3.Lambda expressions can provide the implementation of the

Scan to Download
abstract method of a functional interface directly inline.
4.Method references let you reuse existing method
definitions and pass them like lambdas.
5.The execute-around pattern can be used with lambdas to
gain additional flexibility and reusability.
Chapter 6 | Quotes From Pages 114-130
1.'Streams are an update to the Java API that let
you manipulate collections of data in a declarative
way (you express a query rather than code an ad
hoc implementation for it). '
2.'The result of the filter is passed to the sorted method,
which is then passed to the map method and then to the
collect method.'
3.'The new Streams API is expressive.'
4.'You may be wondering what exactly happens when you
invoke the method parallelStream. How many threads are
being used? What are the performance benefits? Should
you use this method at all?'
5.'In contrast to collections, which are iterated explicitly

Scan to Download
using an iterator, stream operations do the iteration behind
the scenes for you.'
6.'You can think of it as if the method invocations in the
chain are queued up until collect is called.'
7.'A collection is an in-memory data structure that holds all
the values the data structure currently has.'
8.'The internal iteration in the Streams library can
automatically choose a data representation and
implementation of parallelism to match your hardware.'
9.'In coarsest terms, the difference between collections and
streams has to do with when things are computed.'

Scan to Download
Chapter 7 | Quotes From Pages 131-166
1.This different way of working with data is useful
because you let the Streams API manage how to
process the data.
2.With a small list this may not seem like a huge benefit, but
it can become useful if you work with potentially large
streams of elements.
3.Using internal iteration, the Streams API can decide to run
your code in parallel.
4.The Stream interface supports a filter method... and returns
a stream including all elements that match the predicate.
5.The dropWhile operation is the complement of takeWhile...
it even works if there are an infinite number of remaining
elements!
6.You can use the Streams API to express sophisticated data
processing queries.
7.The reduce operation...can help simplify how you combine
elements of a stream to express more complicated queries...
8.Parallelizing this computation requires a different

Scan to Download
approach: partition the input, sum the partitions, and
combine the sums.
9.Streams can be created not only from a collection but also
from values, arrays, files, and specific methods such as
iterate and generate.
10.An infinite stream has an infinite number of elements...but
can also be limited to produce a finite stream.
Chapter 8 | Quotes From Pages 167-204
1.The purpose of the code isn’t immediately evident
at first glance, even though it can be expressed in a
straightforward manner in plain English: "Group
a list of transactions by their currency.
2.In this example, the groupingBy recipe says, "Make a Map
whose keys are (currency) buckets and whose values are a
list of elements in those buckets.
3.Collectors are extremely useful, because they provide a
concise yet flexible way to define the criteria that collect
uses to produce the resulting collection.
4.The implementation of the methods of the Collector

Scan to Download
interface defines how to perform a reduction operation on a
stream.
5.You can obtain the same result by passing the three
functions implementing the core logic of
PrimeNumbersCollector to the overloaded version of the
collect method.
Chapter 9 | Quotes From Pages 205-231
1.By far the most important benefit is the possibility
of executing a pipeline of operations on these
collections that automatically makes use of the
multiple cores on your computer.
2.In particular, we’ll demonstrate that the way a parallel
stream gets divided into chunks, before processing the
different chunks in parallel, can in some cases be the origin
of these incorrect and apparently unexplainable results.
3.When optimizing performance, you should always follow
three golden rules: measure, measure, measure.
4.Choosing the right data structures is often more important
than parallelizing the algorithm that uses them.

Scan to Download
5.Avoiding a shared mutable state ensures that your parallel
stream will produce the right result.
6.If in doubt, measure.
7.The fork/join framework lets you recursively split a
parallelizable task into smaller tasks, execute them on
different threads, and then combine the results of each
subtask in order to produce the overall result.

Scan to Download
Chapter 10 | Quotes From Pages 234-248
1.Your life as a Java developer would be rather
lonely without the Collection API.
2.Java 9 introduced a few convenient ways to create small
collection objects.
3.This behavior seems slightly surprising because the
underlying list is backed by a mutable array of fixed size.
4.Sometimes, though, instead of removing an element, you
want to replace it.
5.If you try to create a Set by providing a duplicated element,
you receive an IllegalArgumentException.
6.The replaceAll method on the List interface lets you
replace each element in a list with a new one.
7.The computeIfAbsent method is also useful for
conveniently dealing with maps that store multiple values.
8.ConcurrentHashMap allows concurrent add and update
operations that lock only certain parts of the internal data
structure.
9.Java 9 supports collection factories, which let you create

Scan to Download
small immutable lists, sets, and maps by using List.of,
Set.of, Map.of, and Map.ofEntries.
10.The Map interface includes several new default methods
for common patterns and reduces the scope for bugs.
Chapter 11 | Quotes From Pages 249-271
1.Lambda expressions can make your code more
readable and flexible.
2.Consider converting anonymous classes to lambda
expressions, but be wary of subtle semantic differences
such as the meaning of the keyword this and shadowing of
variables.
3.Method references can make your code more readable
compared with lambda expressions.
4.Lambda expressions can remove boilerplate code
associated with several object-oriented design patterns,
such as strategy, template method, observer, chain of
responsibility, and factory.
5.Consider extracting complex lambda expressions into
regular methods.

Scan to Download
6.The peek method of a stream is useful for logging
intermediate values as they flow past certain points of a
stream pipeline.
Chapter 12 | Quotes From Pages 272-305
1.Programs must be written for people to read and
only incidentally for machines to execute." -
Harold Abelson
2.Communication is king. Your code should clearly
communicate its intentions and be understandable even by
a non-programmer.
3.Code is written once but read many times. Readability is
vital for maintainability.
4.A DSL is a custom-built language designed to solve a
problem for a specific business domain.
5.An API that conveniently encapsulates the business logic
allows you to avoid repetition, resulting in code that’s less
verbose.
6.If you get the design right, lower-skilled programmers can
write code quickly and effectively...

Scan to Download
7.A specific language for your domain... means that you have
less to worry about and can invest more attention in solving
the business problem at hand.
8.Historically, Java hasn’t been considered to be a
DSL-friendly language because of its cumbersome,
inflexible syntax.
9.Readability, reusability, and composability of code
increase... as DSLs restrict the operations and vocabulary
available to a specific domain.
10.The main purpose of a DSL is to fill the gap between
developers and domain experts.

Scan to Download
Chapter 13 | Quotes From Pages 308-329
1.Tony Hoare introduced null references back in
1965... later saying that he did so 'simply because
it was so easy to implement.'... he regretted this
decision, calling it 'my billion-dollar mistake.'
2.Using null to represent the absence of a value is the wrong
approach. What you need is a better way to model the
absence and presence of a value.
3.With this act in mind, you can rework the original model
from listing 11.1, using the Optional class as shown... A
person may not own a car, so you declare this field
Optional.
4.The intention of the Optional class isn’t to replace every
single null reference. Instead, its purpose is to help you
design more-comprehensible APIs so that by reading the
signature of a method, you can tell whether to expect an
optional value.
5.You can achieve the same result in a single operation
instead of two by using the stream() method of the

Scan to Download
Optional class.
Chapter 14 | Quotes From Pages 330-346
1.The old java.util.Date class and all other classes
used to model dates and times in Java before Java
8 have many inconsistencies and design flaws,
including mutability and some poorly chosen
offsets, defaults, and naming.
2.All the date-time objects of the new Date and Time API are
immutable.
3.You can manipulate date and time objects in both an
absolute and relative manner, and the result of these
manipulations is always a new instance, leaving the
original one unchanged.
4.TemporalAdjusters allow you to manipulate a date in a
more complex way than changing one of its values, and
you can define and use your own custom date
transformations.
5.You can define a formatter to print and parse date-time
objects in a specific format.

Scan to Download
6.You can represent a time zone, relative to a specific
region/location and as a fixed offset from UTC/Greenwich,
and apply it to a date-time object to localize it.
7.You can use calendar systems different from the ISO-8601
standard system.
Chapter 15 | Quotes From Pages 347-365
1.Java 8 introduced a new mechanism to tackle this
problem.
2.Default methods are new in Java 8 to evolve APIs in a
compatible way.
3.A common pattern in Java is to define both an interface and
a utility companion class.
4.Default methods provide a means of evolving interfaces
without modifying existing implementations.
5.Keeping interfaces minimal and orthogonal lets you
achieve great reuse and composition of behavior inside
your code base.
6.Three resolution rules to know: Classes always win.
7.If there’s still a conflict, you have to explicitly override the

Scan to Download
default methods and choose which one your class should
use.

Scan to Download
Chapter 16 | Quotes From Pages 366-387
1.Before you delve into the details of the Java
Module System, it’s useful to understand some
motivation and background to appreciate the goals
set out by the Java language designers.
2.Separation of concerns (SoC) is a principle that promotes
decomposing a computer program into distinct features.
3.Information hiding is a principle that encourages hiding
implementation details.
4.Java 9 introduces a new module system in which a
module-info.java file names a module and specifies its
dependencies (requires) and public API (exports).
5.The Class Path Hell problem makes it hard to reason about
the dependencies of an application.
6.The requires clause lets you specify dependencies on other
modules.
7.A module’s declaration doesn’t include a version string.
Chapter 17 | Quotes From Pages 390-419
1.To implement applications like this, you have to

Scan to Download
contact multiple web services across the Internet.
But you don’t want to block your computations
and waste billions of precious clock cycles of your
CPU waiting for an answer from these services.
2.Java offers two main tool sets for such circumstances. First,
as you’ll see in chapters 16 and 17, the Future interface,
and particularly its Java 8 CompletableFuture
implementation, often provide simple and effective
solutions.
3.The takeaway idea is that parallel Stream iteration is a
higher-level concept than explicit use of threads.
4.The box-and-channel model can be used to structure
thoughts and code...you draw boxes (or use combinators in
programs) to express the computation you want, which is
later executed, perhaps more efficiently than you might
have obtained by hand-coding the computation.
5.The CompletableFuture class expresses one-shot
asynchronous computations. Combinators can be used to
compose asynchronous computations without the risk of

Scan to Download
blocking that’s inherent in traditional uses of Futures.
6.A reactive system is a program whose architecture allows it
to react to changes in its runtime environments. Properties
that reactive systems should have are formalized in the
Reactive Manifesto...
Chapter 18 | Quotes From Pages 420-448
1.Executing relatively long-lasting operations by
using asynchronous tasks can increase the
performance and responsiveness of your
application, especially if it relies on one or more
remote external services.
2.You should consider providing an asynchronous API to
your clients.
3.A CompletableFuture allows you to propagate and manage
errors generated within an asynchronous task.
4.You can compose or combine multiple asynchronous tasks
when they’re independent and when the result of one of
them is used as the input to another.
5.You can register a callback on a CompletableFuture to

Scan to Download
reactively execute some code when the Future completes
and its result becomes available.

Scan to Download
Chapter 19 | Quotes From Pages 449-475
1.Modern applications demand responsiveness,
resilience, elasticity, and message-driven
architecture, making reactive programming
increasingly relevant.
2.A reactive system has a fast and consistent, predictable
response time. As a result, the user knows what to expect.
3.The main feature of reactive programming for
application-level components allows tasks to be executed
asynchronously.
4.These features and advantages that characterize reactive
applications and systems are crystallized in the Reactive
Manifesto, which we discuss in the next section.
5.Developing applications by following the reactive
principles is only one aspect of reactive programming and
often not even the hardest one.
6.Resilience in reactive architectures is more than
fault-tolerance. The system doesn’t gracefully degrade but
fully recovers from failures by isolating them and bringing

Scan to Download
the system back to a healthy state.
7.Reactive programming addresses these issues by allowing
you to process and combine streams of data items coming
from different systems and sources in an asynchronous
way.
8.Good systems-architectural style avoids making visible
throughout the system any fine-details concepts that are
used in only one part of the system.
9.The Java 9 Flow API defines four core interfaces:
Publisher, Subscriber, Subscription, and Processor.
10.These principles can be applied, with some differences, in
implementing a single application and in designing a
reactive system that integrates multiple applications.
Chapter 20 | Quotes From Pages 478-492
1.Functional programming exemplifies this idea of
declarative programming (say what you want
using expressions that don’t interact, and for
which the system can choose the implementation)
and side-effect-free computation.

Scan to Download
2.The idea of no side effects may appear to be a severe
restriction, and you may doubt whether real systems can be
built this way.
3.Taking advantage of the fact that an Integer object is
immutable; otherwise, you’d have to clone each element
too.
4.Takeaway point: thinking of programming problems in
terms of function-style methods that are characterized only
by their input arguments and output results (what to do) is
often more productive than thinking about how to do it and
what to mutate too early in the design cycle.
5.A function is referentially transparent if it always returns
the same result value when it’s called with the same
argument value.
Chapter 21 | Quotes From Pages 493-517
1.Thinking in terms of side-effect-free methods can
help you write more maintainable code.
2.Functions that may be used like other values are referred to
as first-class functions.

Scan to Download
3.Currying is a technique that can help you modularize
functions and reuse code.
4.A functional-style method isn’t allowed to update any
global data structure or any structure passed as a parameter.
5.Lazy lists also provide an excellent way of thinking about
higher-order functions.
6.Referential transparency allows computations to be cached.

Scan to Download
Chapter 22 | Quotes From Pages 518-532
1.We believe that it’s important for a well-rounded
software engineer to be knowledgeable about the
wider programming-languages ecosystem.
2.You’ll find that you can write more concise and readable
code in Scala compared with Java, for example.
3.Immutability is useful because you know that accessing the
collection at any point in your program always yields a
collection with the same elements.
4.Functions in Scala are first-class values, which means that
they can be passed around as parameters, returned as a
result, and stored in variables, like values such as Integer
and String.
5.Scala supports traits, which are Scala’s replacement for
Java’s interfaces.
6.You can create a Map and associate a key with a value
directly, using the syntax ->.
Chapter 23 | Quotes From Pages 533-549
1.Java 8 represents perhaps the biggest evolution

Scan to Download
step ever taken by Java.
2.A shorter development cycle enables Java to evolve at the
right speed and allows the language to remain relevant and
appropriate in the coming years.
3.The new Java module system enables the Java runtime to
be split into smaller parts, so you can use only the parts that
are necessary for your application.
4.We hope that you’ve enjoyed this learning adventure with
us and that we’ve sparked your interest in exploring the
further evolution of Java.
5.Java 11 allows the var syntax of local-variable type
inference to be used in the list of parameters of an
implicitly typed lambda expression.
Chapter 24 | Quotes From Pages 550-552
1.Annotations are a mechanism that lets you
decorate program elements with additional
information.
2.This new mechanism as syntactic sugar around the
previous idiom used by Java programmers.

Scan to Download
3.Annotations can be used for documentation.
4.Annotations can also be popular in Java EE, where they’re
used to configure enterprise applications.
5.Annotations on types can be useful to perform program
analysis.

Scan to Download
Chapter 25 | Quotes From Pages 553-553
1.Java 8 enhances the inference of generic
arguments.
2.In Java 8 the target type includes arguments to a method, so
you don’t need to provide an explicit generic argument.
3.You can call it as follows to provide an explicit type to the
type parameter: List<Car> cars =
Collections.<Car>emptyList();
4.In this code, it’s exactly this enhancement that lets you
write Collectors.toList() instead of
Collectors.<Car>toList().
Chapter 26 | Quotes From Pages -556
1.The method getOrDefault can be used to replace
an existing idiom that checks whether a Map
contains a mapping for a given key.
2.Another particularly useful method is computeIfAbsent,
which... lets you conveniently use the caching pattern.
3.The removeIf method can be used to remove all elements
in a collection that match a predicate.

Scan to Download
4.The replaceAll method replaces each element in a List with
the result of applying a given operator to it.
5.The Comparator interface now includes default and static
methods.
Chapter 27 | Quotes From Pages -558
1.Java 8 brings several updates related to
concurrency.
2.The java.util.concurrent.atomic package offers several
numeric classes, such as AtomicInteger and AtomicLong
that support atomic operation on single variables.
3.The Java API recommends using the new classes
LongAdder, LongAccumulator, DoubleAdder, and
DoubleAccumulator instead of the Atomic classes
equivalent when multiple threads update frequently but
read less frequently.
4.ConcurrentHashMap allows concurrent add and updates
that lock only certain parts of the internal data structure.
5.Entries of a map are typically stored in buckets accessed by
the generated hashcode of the key.

Scan to Download
6.The operations will execute sequentially if the current map
size is estimated to be less.

Scan to Download
Chapter 28 | Quotes From Pages -undefined
1.Using a value of 1 enables maximal parallelism
using the common thread pool.
2.The ConcurrentHashMap class provides a new method
called mappingCount, which returns the number of
mappings in the map as a long.
3.The setAll and parallelSetAll methods set all elements of
the specified array, respectively sequentially or in parallel,
using the provided function to compute each element.
4.Because parallelSetAll is executed in parallel, the function
must be side-effect free, as explained in chapters 7 and 18.
Chapter 29 | Quotes From Pages -560
1.The parallelPrefix method cumulates, in parallel,
each element of the given array, using the supplied
binary operator.
2.The Java 8 API enhances the Number and Math classes
with new methods.
3.The BigInteger class includes the methods byteValueExact,
shortValueExact, intValueExact, and longValueExact, to

Scan to Download
convert this BigInteger to the respective primitive type.
4.The Math class includes new methods that throw an
arithmetic exception if the result of the operation
overflows.
Chapter 30 | Quotes From Pages 561-561
1.Files.lines in chapter 5; it lets you read a file lazily
as a stream.
2.Files.walk—Just like Files.list, it produces a Stream<Path>
consisting of entries in a given directory.
3.Information about parameters of methods such as names
and modifiers can now be accessed with the help of the
new java.lang.reflect.Parameter class.
4.The String class now includes a convenient static method
called join to—as you may guess—join strings with a
delimiter!

Scan to Download
Chapter 31 | Quotes From Pages 563-569
1.The StreamForker provides a convenient, fluent
API to fork a stream and assign a different
operation to each forked stream.
2.These operations are expressed in terms of functions
applied on the stream and can be identified by any arbitrary
object; in this case we’ve chosen to use Strings.
3.If in the meantime the computation of that operation
completes, the get method will return the corresponding
result; otherwise, it will block until such a result isn’t
available.
4.When you have no more forks to add, you can invoke
getResults on the StreamForker to trigger the execution of
all the defined operations and obtain StreamForker.Results.
Chapter 32 | Quotes From Pages 571-571
1....lambdas were translated to anonymous classes,
you’d have one new class file for each lambda.
2.Each new anonymous class introduces a new subtype for a
class or interface.

Scan to Download
Chapter 33 | Quotes From Pages 572-572
1.Bytecode generation mean a hundred different
subtypes of Comparator. In certain situations, this
can make it harder to improve runtime
performance by the JVM.
2.The JVM can then execute the generated bytecode and run
the application.
3.Anonymous classes and lambda expressions use different
bytecode instructions when they’re compiled.
4.Let’s try to implement an instance of the Function interface
using the old Java 7 syntax, as an anonymous inner class.
5.This code shows the following: An object of type
InnerClass$1 is instantiated using the byte code operation
new.

Scan to Download
Chapter 34 | Quotes From Pages 573-573
1.The creation of an extra class has been replaced
with an invokedynamic instruction.
2.invokedynamic adds a further level of indirection when
invoking a method, to let some logic dependent on the
specific dynamic language determine the call target.
3.The typical use for this instruction is something like the
following: def add(a, b) { a + b }
Chapter 35 | Quotes From Pages 574-575
1.The strategy used to translate the lambda
expression body to bytecode becomes a pure
implementation detail.
2.There’s no overhead, such as additional fields or static
initializer, if the lambda is never used.
3.For stateless (noncapturing) lambdas it’s possible to create
one instance of the lambda object, cache it, and always
return the same.
4.The call site itself can contain the logic defining under
which conditions it needs to be relinked.

Scan to Download
Chapter 36 | Quotes From Pages 576-576
1.As Java moves forward, it encourages developers
to embrace functional programming paradigms
alongside the established object-oriented
techniques.
2.CompletableFuture is a powerful tool that carries the
promise of simpler and more efficient asynchronous
programming.
3.Refactoring code to leverage lambda expressions can lead
to more concise and readable implementations.
4.The future of Java is not just about new features, but about
how we think about programming.

Scan to Download
Chapter 37 | Quotes From Pages 577-578
1.The future is not something we enter. The future is
something we create.
2.Every problem is a gift—without problems, we would not
grow.
3.Innovation is not born from the rigid adherence to the past.
4.In every job that must be done, there is an element of fun.
5.Quality is never an accident; it is always the result of
intelligent effort.
Chapter 38 | Quotes From Pages 579-579
1.Modern Java allows us to express what we mean
more clearly, with fewer lines of code.
2.Embracing functional programming paradigms can lead to
more predictable and maintainable code.
3.With Java's robust API features, we can streamline
complex data processing tasks elegantly.
4.Effective use of concurrency enables applications to make
the most of available system resources.
5.Design patterns in Java provide proven solutions to

Scan to Download
common software design problems.
Chapter 39 | Quotes From Pages 580-580
1.Encapsulation is the cornerstone of robust
software design.
2.Behavior parameterization allows flexibility in design
without compromising functionality.
3.Reactive programming is essential for handling
asynchronous data streams efficiently.
4.Domain-specific languages empower developers to express
solutions better suited for their specific contexts.
5.First-class functions unlock a new level of abstraction in
programming.

Scan to Download
Chapter 40 | Quotes From Pages 581-581
1.Functional programming offers a powerful way to
build scalable and maintainable systems by
promoting immutability and higher-order
functions.
2.Declarative programming lets you express the 'what' rather
than the 'how', leading to cleaner and more concise code.
3.Referential transparency is a key concept in functional
programming, ensuring that functions can be replaced with
their values without affecting program behavior.
4.Currying allows functions to be partially applied,
enhancing flexibility and composition in programming.
5.Immutability in data structures promotes safer code,
eliminating unintended side effects and improving
predictability.
Chapter 41 | Quotes From Pages 582-582
1.The future of Java is very bright, fueled by
innovations that focus on improving productivity,
enhancing performance, and elevating developer

Scan to Download
experience.
2.Modularity in Java allows for more manageable code,
improved maintainability, and facilitates greater
collaboration in software development.
3.With advancements in features like pattern matching and
value types, Java continues to evolve, ensuring it meets the
needs of modern developers.
4.Java’s rich library ecosystem is a testament to the vibrant
community that continuously contributes to its evolution.
5.Understanding the fundamental concepts of streams and
functional programming in Java can significantly enhance a
developer's efficiency and effectiveness.
Chapter 42 | Quotes From Pages 583-583
1.Behavior parameterization is a powerful and
flexible tool that encourages clean code design by
externalizing behavior from algorithms.
2.In functional programming, functions can be treated as
first-class citizens, which means they can be assigned to
variables, passed as parameters, and returned from other

Scan to Download
functions.
3.The general idea of streams is to provide a higher-level
abstraction that allows you to process sequences of
elements with minimal overhead.
4.Lazy evaluation allows you to define potentially infinite
data structures that can produce values on demand.
5.Incorporating functional interfaces and lambda expressions
into your codebase can significantly enhance clarity and
reduce boilerplate, leading to more concise solutions.

Scan to Download
Chapter 43 | Quotes From Pages 584-584
1.Methods as first-class values allow us to treat
behavior as parameters in a more natural way,
leading to cleaner and more modular code.
2.Modern languages that support functional programming
paradigms enable us to express complex operations
succinctly, transforming the way we write and think about
code.
3.Lambda expressions provide a clear and concise way to
write anonymous methods in Java, contributing to better
readability and maintainability.
4.The notion of immutability leads us to safer multithreading
practices, ensuring that state is not unintentionally changed
by concurrent processes.
5.By applying functional programming concepts, we can
manipulate collections in Java with ease, making our
operations more expressive and less error-prone.
Chapter 44 | Quotes From Pages 585-585
1.modeling the absence of value 276–280

Scan to Download
2.reducing NullPointerExceptions with defensive checking
277–278
3.alternatives to null in other languages 279–280
4.modeling the absence of value 276–280
5.rejecting certain values with filter 290–291
Chapter 45 | Quotes From Pages 586-586
1.Parallelism is not just a performance optimization,
it's a fundamental change in how we approach
programming.
2.Using parallel streams can make our code simpler and
more expressive.
3.Effective parallelism requires consideration of both the
workload and the structure of the data.
4.Reactive programming can help us build responsive
systems that can easily adapt to changing conditions.
5.Pure functions are fundamental in creating predictable and
maintainable code.

Scan to Download
Chapter 46 | Quotes From Pages 587-588
1.Reactive programming is not just a technique; it’s
a mindset that changes how we approach problems
in programming.
2.With the rise of asynchronous programming models,
traditional paradigms are no longer sufficient to tackle
real-world challenges effectively.
3.Observables are the heart of reactive programming,
enabling a seamless flow of data through different parts of
your system.
4.Backpressure is a crucial concept in ensuring that your
application can handle data flows without overwhelming
resources.
5.Refactoring code not only improves flexibility but also
fosters innovation by allowing developers to experiment
without fear of breaking existing functionality.
Chapter 47 | Quotes From Pages 589-589
1.Parallel computations can dramatically improve
performance, but only if the problem is

Scan to Download
decomposable and the overhead of coordination is
small.
2.Streams allow you to express complex data transformations
in a more readable way than traditional approaches.
3.Embracing immutability can lead to safer,
easier-to-understand multithreaded applications.
4.Functional-style programming encourages a focus on what
to do rather than how to do it.
5.Reactive programming is about building systems that react
to changes in data or user input asynchronously.
Chapter 48 | Quotes From Pages 590-592
1.Modern applications take advantage of innovative
designs, including microservices, reactive
architectures, and streaming data.
2.Modern Java features like lambdas, streams, and the
long-awaited Java Module System make implementing
these designs significantly easier.
3.It will help you expand your existing knowledge of core
Java as you master modern additions like the Streams API

Scan to Download
and the Java Module System, explore new approaches to
concurrency, and learn how functional concepts can help
you write code that’s easier to read and maintain.
4.Hands-on Java 8 and 9, simply and elegantly explained.

Scan to Download
Modern Java in Action Questions
View on Bookey Website

Chapter 1 | How this book is organized: a roadmap|


Q&A
1.Question
What are Java 8 streams, and how do they differ from
collections?
Answer:Java 8 streams are an abstraction that allow
processing sequences of elements (like collections) in
a functional, declarative style. Unlike collections,
streams are designed for more efficient data
processing as they don't require all data to be in
memory at once, and they allow for automatic
optimization such as parallel processing and
grouping multiple operations for efficiency.

2.Question
How does functional-style programming enhance Java
development?
Answer:Functional-style programming enhances Java
development by allowing functions to be treated as first-class

Scan to Download
values. This leads to more concise and flexible code. Java 8
integrated these principles, enabling developers to write
clearer code that adapts easily to changing requirements,
much like having additional tools in a programming toolbox.

3.Question
What is the significance of the lambda expressions
introduced in Java 8?
Answer:Lambda expressions are anonymous functionalities
that facilitate behavior parameterization, simplifying code
syntax for writing internal implementation of a functional
interface. They allow developers to implement methods
defined in interfaces more succinctly, enhancing clarity and
reducing boilerplate code.

4.Question
How can Java 8's Optional class improve API design?
Answer:The Optional class helps in preventing null pointer
exceptions by providing a container that may or may not hold
a value. This leads to better API design, encouraging
developers to explicitly handle potential absence of values

Scan to Download
rather than relying on null checks.

5.Question
What advantages does adopting the Java Module System
in Java 9 provide?
Answer:The Java Module System allows for modularization
of large applications, enhancing organization and
maintainability. It enforces access controls, ensuring that
modules only expose necessary parts of their functionality,
reducing the potential for errors and improving the clarity of
dependencies.

6.Question
In what way does the book structure support a layered
learning approach?
Answer:The book is structured in six parts where the first
two lay the fundamental concepts necessary for
understanding subsequent chapters. This organization allows
readers to build knowledge progressively, grasping essential
features like lambda expressions and streams before
exploring more complex topics.

Scan to Download
7.Question
What role do quizzes play in the learning process as
described in the book?
Answer:Quizzes are included in most chapters to reinforce
learning, allowing readers to apply concepts and check their
understanding of the material presented, which enhances
retention and comprehension.

8.Question
How does the new Date and Time API in Java 8 improve
developer efficiency?
Answer:The new Date and Time API in Java 8 significantly
simplifies the manipulation and formatting of dates and times
while addressing many of the pitfalls and limitations of
previous date handling methods, thus reducing bugs and
enhancing code reliability.

9.Question
What is the focus of the final part of the book regarding
functional programming techniques?
Answer:The final part of the book provides an introduction to
writing effective functional-style programs in Java, covering

Scan to Download
techniques such as higher-order functions and pattern
matching, aimed at improving software development
efficiency and understanding the broader context of
programming paradigms.

10.Question
Why is it beneficial to compare Java 8 features with Scala
language features as suggested in the book?
Answer:Comparing Java 8 features with Scala helps to
highlight Java's strengths and potential areas for
improvement. It also provides insights into how other
languages can influence Java development and foster a
deeper understanding of functional programming concepts.
Chapter 2 | Book forum| Q&A
1.Question
What is the primary focus of Chapter 2 in 'Modern Java
in Action'?
Answer:Chapter 2 primarily focuses on the
fundamentals of Java 8, particularly the
introduction and advantages of functional-style

Scan to Download
programming as a transition from traditional
object-oriented approaches.

2.Question
What can readers expect to learn from the appendices
mentioned in the book?
Answer:Readers can expect to learn about minor language
features of Java 8, additional library features that enhance
Java's functionality, advanced uses of streams, and the
underlying mechanics of how lambda expressions are
implemented by the Java compiler.

3.Question
How does the author encourage reader engagement and
dialogue about the book's content?
Answer:The author encourages reader engagement by
providing access to a private web forum where readers can
discuss content, ask questions, and interact with both the
authors and fellow learners, promoting a community of
shared learning.

4.Question
What benefits does the author mention regarding the

Scan to Download
availability of source code for the examples in the book?
Answer:The availability of source code allows readers to
practically apply what they're learning by experimenting with
real examples, enhancing their understanding of Java
concepts and enabling hands-on practice.

5.Question
Why is it important for readers to engage with the
authors on the forum?
Answer:Engaging with the authors on the forum is important
because it allows readers to ask challenging questions and
dive deeper into the material, ensuring a richer and more
insightful learning experience.

6.Question
What do the authors imply about the future of Java
beyond version 8?
Answer:The authors imply that there are exciting
developments and enhancements on the horizon for Java
beyond version 8, suggesting an ongoing evolution of the
language that readers should look forward to.

Scan to Download
7.Question
In what ways does the structure of the book support
different learning styles?
Answer:The structure of the book, including code examples,
annotations, appendices for deeper exploration, and a
discussion forum, supports different learning styles by
catering to both visual learners (through code illustrations)
and those who prefer interactive dialogue and discussion.

8.Question
What is the significance of the source code repository
mentioned in the book?
Answer:The source code repository serves as a practical
resource for readers, enabling them to download and run the
examples provided in the book, thereby reinforcing their
learning through direct application.
Chapter 3 | 1 Java 8, 9, 10, and 11: what?s
happening?| Q&A
1.Question
What are the major changes introduced in Java 8 that set
it apart from previous versions?

Scan to Download
Answer:Java 8 introduced several key features that
revolutionized Java programming: 1. The Streams
API, which allows for processing sequences of data
in a functional style, enabling operations like
filtering, mapping, and reducing collections with
improved readability and efficiency. 2. Lambda
expressions, which provide a syntax for passing
behavior (methods) as parameters, allowing for
more concise and expressive code. 3. Default
methods in interfaces, enabling interfaces to evolve
without breaking existing implementations. These
features collectively enhance code conciseness and
ease of parallel processing on multicore systems.

2.Question
Why is the concept of first-class functions important in
Java 8?
Answer:First-class functions in Java 8 allow methods to be
treated as values that can be passed and used as arguments in
other methods. This enables higher-order programming,

Scan to Download
where behavior can be abstracted and reused efficiently. It
leads to more expressive and maintainable code, as
developers can leverage pre-defined functions without
creating verbose class structures.

3.Question
How does Java 8 improve the handling of concurrency in
programming?
Answer:Java 8 addresses concurrency through the Streams
API, which allows for internal iteration and parallel
processing without the complexity traditionally associated
with multithreading. By avoiding shared mutable data and
utilizing a functional programming approach, developers can
write concurrent code that is less prone to errors and easier to
understand.

4.Question
What is the significance of the Lambda expression in Java
8, and how does it benefit programmers?
Answer:Lambda expressions allow programmers to write
anonymous functions succinctly by eliminating the

Scan to Download
boilerplate of creating separate classes for simple behavior.
This results in cleaner, more readable code, particularly when
working with collection operations such as filtering and
transforming data. It enhances the expressiveness of the
language and encourages functional programming
paradigms.

5.Question
What role do default methods play in Java 8's interface
evolution?
Answer:Default methods allow interfaces to provide concrete
implementations of methods while preserving backward
compatibility. This means that existing classes implementing
the interface do not need to be modified when new methods
are added, mitigating the challenges of evolving large
systems and enabling more flexible library development.

6.Question
How do Streams in Java 8 facilitate parallel processing?
Answer:Streams abstract the management of parallelism by
allowing developers to process collections with methods like

Scan to Download
'parallelStream', which automatically partitions data for
concurrent processing across multiple CPU cores. This
significantly simplifies the coding of parallel algorithms, as
developers can focus on the 'what' of data processing instead
of the 'how' of implementing thread management.

7.Question
Why should Java developers care about the evolution of
the language with each new version?
Answer:Java developers should care about ongoing language
evolution as it introduces new features that improve
productivity, enhance performance, and keep the language
relevant in a rapidly changing technological landscape. The
addition of modern programming concepts in Java 8 and
beyond makes it easier to tackle contemporary programming
challenges, particularly in areas like big data, concurrency,
and maintainability.

8.Question
In what ways does the new Java module system in Java 9
improve the organization of large applications?

Scan to Download
Answer:The module system in Java 9 allows developers to
define modules that encapsulate packages within a single
cohesive component. This promotes better visibility
management, stricter access control, and clearer dependency
management across large applications, making it easier to
maintain and evolve complex systems without conflicts
between components.

9.Question
What are some functional programming concepts
introduced in Java 8?
Answer:Java 8 introduced several functional programming
concepts, including: 1. First-class functions: treating methods
as values. 2. Higher-order functions: functions that can take
other functions as inputs or return them as outputs. 3.
Immutable data structures: promoting the use of immutability
to prevent unintended side effects. 4. Enhanced data
processing capabilities through the Streams API: enabling
map, filter, and reduce operations.

10.Question

Scan to Download
How can Java's evolution affect a developer's career
opportunities?
Answer:As Java evolves to include modern features,
developers who familiarize themselves with the latest
updates are better positioned in the job market. Mastery of
new concepts like streams, lambdas, and modular
programming not only enhances a developer's skill set but
also aligns them with current industry standards, increasing
their employability in a competitive landscape.

Scan to Download
Chapter 4 | 2 Passing code with behavior
parameterization| Q&A
1.Question
What is behavior parameterization and why is it
important in software development?
Answer:Behavior parameterization is a software
design pattern that allows developers to cope with
changing requirements by passing blocks of code
(behaviors) as parameters to methods without
executing them immediately. This pattern is
important because it makes code more flexible,
enabling easy adjustments to functionality without
needing to rewrite or duplicate code, which
significantly reduces engineering effort and
enhances maintainability.

2.Question
How can behavior parameterization help when user
requirements change frequently, such as in the case of
filtering apples by various attributes?
Answer:Behavior parameterization allows you to create a

Scan to Download
single filtering method that can take different criteria (like
color or weight) as parameters. Instead of writing separate
methods for each filtering condition, you can pass different
behaviors or predicates to a generic filtering method,
enabling quick adaptations to new or modified requirements.

3.Question
What are some real-world examples of using behavior
parameterization in Java?
Answer:1. **Sorting with a Comparator**: You can
parameterize sorting behavior by passing a Comparator to a
sort method, enabling the sorting of collections based on
different attributes. 2. **Executing code with Runnable**:
Threads can be created with different behaviors by passing a
Runnable implementation to them. 3. **Callable for
results**: The Callable interface can be used to submit tasks
to a thread pool that return results, enhancing flexibility in
concurrent programming. 4. **Event Handling in GUIs**:
Event handlers can be parameterized to define how a
program responds to user events, enhancing user experience

Scan to Download
and responsiveness.

4.Question
What improvements do lambda expressions bring to
behavior parameterization in Java?
Answer:Lambda expressions, introduced in Java 8,
significantly reduce verbosity in code by allowing the
definition of behaviors as short, inline expressions instead of
requiring the creation of separate classes or anonymous
classes. This leads to cleaner, more readable code while
maintaining the flexibility that behavior parameterization
provides.

5.Question
Can you describe the strategy design pattern in relation
to behavior parameterization?
Answer:The strategy design pattern defines a family of
algorithms, encapsulating each one in its own class and
making them interchangeable at runtime. In the context of
behavior parameterization, you can consider different
implementations of a behavior (e.g., various predicates for

Scan to Download
filtering apples) as strategies that can be passed as parameters
to a method, allowing for flexible and dynamic changes in
behavior.

6.Question
Why should developers avoid using flags to differentiate
between different filtering criteria in methods?
Answer:Using flags to differentiate between filtering criteria
creates unclear, hard-to-read code, leading to potential errors
and maintenance challenges. Instead, separating behavior
into distinct predicate implementations allows for clearer,
more legible code, where each filtering behavior is defined
independently, enhancing the overall design and readability.

7.Question
What is a practical benefit of parameterizing methods
with behavior in terms of code maintenance?
Answer:Parameterizing methods with behavior promotes
code reuse and adheres to the DRY (Don't Repeat Yourself)
principle, reducing the need for duplicate code. This practice
makes maintaining and updating the code easier, as changes

Scan to Download
can be made in one place rather than in multiple duplicated
methods, facilitating long-term software evolution and
reducing engineer workload.

8.Question
How does behavior parameterization relate to the concept
of separating logic from behavior?
Answer:Behavior parameterization allows developers to
separate the core logic of iterating through collections from
the specific behaviors or conditions that apply to those
collections. This separation enhances code clarity and makes
it easier to modify or extend individual behaviors without
changing the core logic, leading to more modular and
maintainable code.

9.Question
What role does the Predicate interface play in behavior
parameterization for filtering methods?
Answer:The Predicate interface serves as a general
representation of behaviors that can be applied to items in a
collection. By taking a predicate as a parameter in filtering

Scan to Download
methods, you enable flexible and reusable filtering criteria,
as any implementation of the Predicate interface can be
passed to define various conditions for filtering items,
enhancing adaptability to changing requirements.

10.Question
How does the chapter suggest dealing with verbosity
prior to the introduction of lambda expressions?
Answer:To manage verbosity before lambda expressions, the
chapter introduces anonymous classes, which allow
developers to create ad hoc implementations of interfaces
without needing to formally declare new classes. However,
even anonymous classes can be bulky and cumbersome,
which is why lambda expressions offer a more concise and
clear alternative in modern Java.
Chapter 5 | 3 Lambda expressions| Q&A
1.Question
What are lambda expressions and why are they
important in Java 8?
Answer:Lambda expressions are concise

Scan to Download
representations of anonymous functions that can be
passed around. They are important because they
simplify the syntax for passing behavior in Java,
allowing for clearer and more flexible code.
Previously, behavior parameterization often
required verbose anonymous classes, but with
lambdas, this can be done concisely, encouraging
better coding practices.

2.Question
How do you create a lambda expression in Java?
Answer:A lambda expression is created using the syntax
(parameters) -> expression. For example, (String s) ->
s.length() defines a lambda that takes a String and returns its
length. If there are multiple statements in the body, curly
braces are required, for instance: (int x, int y) -> { return x +
y; }.

3.Question
What is a functional interface, and why are they relevant
for lambda expressions?

Scan to Download
Answer:A functional interface is an interface that has exactly
one abstract method. They are relevant for lambda
expressions because lambdas can only be used where a
functional interface is expected, meaning they provide a
target type for the lambda expression, enabling the compiler
to determine the context in which the lambda operates.

4.Question
Can you give an example of how to use a lambda
expression in filtering a list?
Answer:Certainly! For example, if you have a list of apples
and you want to filter out only green apples, you can use the
following code: List<Apple> greenApples = filter(inventory,
(Apple a) -> GREEN.equals(a.getColor())); In this code, the
lambda expression specifies the condition for filtering.

5.Question
What is meant by the 'execute-around pattern' in the
context of lambda expressions?
Answer:The 'execute-around pattern' refers to a common
coding pattern where you encapsulate a sequence of

Scan to Download
operations, such as resource management, that surround a
specific behavior. With lambdas, you can pass the behavior
you want executed between setup and cleanup operations,
leading to more reusable and flexible code.

6.Question
What does method reference mean in Java 8, and how
does it improve code readability?
Answer:Method references provide a way to refer to methods
by their names as a shorthand for lambdas. For example,
instead of writing a full lambda to retrieve an apple's weight,
you can use the method reference Apple::getWeight,
improving code readability and making it clearer what
operation is being performed.

7.Question
How can you combine predicates in Java using lambda
expressions?
Answer:You can combine predicates using methods like and,
or, and negate. For instance, if you have a predicate for red
apples, you can create a new predicate that checks for red and

Scan to Download
heavy apples using: Predicate<Apple> redAndHeavy =
redApplePredicate.and(a -> a.getWeight() > 150); This
results in a more descriptive and readable code.

8.Question
What are the common functional interfaces provided in
the Java 8 API?
Answer:Some common functional interfaces in the Java 8
API include Predicate<T>, Consumer<T>, Function<T, R>,
Supplier<T>, and BinaryOperator<T>. These interfaces
capture different kinds of operations and are designed to
work seamlessly with lambda expressions.

9.Question
How does Java's type inference work with lambda
expressions?
Answer:Java's type inference allows the compiler to deduce
the types of lambda parameters based on the target type
context. For example, when a lambda is passed to a method
that expects a functional interface, the compiler checks the
method's signature and infers the parameter types from there,

Scan to Download
allowing for simpler and cleaner lambda syntax.

10.Question
Explain the significance of default methods in functional
interfaces.
Answer:Default methods in functional interfaces allow these
interfaces to provide concrete method implementations
without breaking existing implementations. This means that
you can add new behavior to interfaces without requiring
changes to all existing implementations, which enhances
code reusability and maintainability.
Chapter 6 | 4 Introducing streams| Q&A
1.Question
What are the primary benefits of using streams in Java
over traditional collections?
Answer:1. **Declarative Style**: Streams allow
programmers to express what they want in a more
readable and concise manner. Instead of detailing
how to traverse a collection, you specify the desired
outcome directly (e.g., find all low-caloric dishes).

Scan to Download
2. **Chaining Operations**: Streams support
chaining multiple operations together, enabling
complex data processing in a clear pipeline format.
This allows for operations like filtering, sorting, and
mapping to be easily combined.
3. **Internal Iteration**: Streams manage iteration
internally, meaning you do not have to deal with the
complexity of loops and iterators, making code
simpler and often more efficient.
4. **Lazy Evaluation**: Stream operations are
processed only when necessary, leading to potential
performance optimizations like short-circuiting
during execution, thereby avoiding unnecessary
computations.

2.Question
Can you explain the difference between intermediate and
terminal operations in streams?
Answer:Intermediate operations (e.g., filter, map) return
another stream and can be chained together to create a

Scan to Download
pipeline without producing a result immediately; they only
execute when a terminal operation is invoked. Terminal
operations (e.g., forEach, collect) produce a non-stream
result and trigger the execution of the entire stream pipeline.

3.Question
What analogy can help explain the concept of a stream
versus a collection?
Answer:A collection is like a DVD movie that holds all the
data you need, stored and accessible at once. A stream,
however, is like watching a movie that is being streamed
over the internet. You can start watching it before the entire
movie is downloaded, as it delivers frames on demand, only
processing what's needed at the moment.

4.Question
Why is internal iteration considered a significant
advantage in streams as compared to external iteration
used in collections?
Answer:Internal iteration abstracts the complexity of
managing iteration from the user, allowing for optimizations
such as parallel processing and flexibility in execution order.

Scan to Download
When using external iteration (like for-each or iterators), you
are responsible for the iteration mechanism and any potential
parallelism, complicating the code and reducing efficiency.

5.Question
How does the Streams API handle parallel processing?
Answer:The Streams API allows for easy parallelization by
simply replacing `stream()` with `parallelStream()`. The
underlying framework handles thread management and
optimizations, enabling improved performance without
requiring programmers to write complex multithreaded code.

6.Question
What happens when you try to traverse a stream more
than once?
Answer:A stream can be traversed only once. Once it has
been consumed (i.e., you have iterated through its elements),
any further attempts to iterate through the same stream will
result in an exception indicating that the stream has already
been operated upon or closed.

7.Question
Can you provide a specific example of how streams can

Scan to Download
simplify code?
Answer:Consider a task where you want to collect the names
of all dishes with more than 300 calories. Using collections,
you might write a loop to iterate through each dish, check its
calories, and build a new list. With streams, it can be done in
one line:
`List<String> names = menu.stream().filter(dish ->
dish.getCalories() >
300).map(Dish::getName).collect(toList());`
This one-liner is not only more readable but also allows for
better performance optimizations.

8.Question
What are the key characteristics of streams that
contribute to their functionality?
Answer:1. **Pipelining**: Streams support combining
operations into a pipeline, allowing for neatly chaining
operations like filter, map, and sort.
2. **Lazy Evaluation**: Elements are computed only as
needed, enabling efficiency in operations.

Scan to Download
3. **Internal Iteration**: Abstracts away the need for explicit
iteration, simplifying code and allowing for automatic
optimizations.

9.Question
What are some real-world scenarios where you would
prefer using streams over collections?
Answer:1. **Data Analysis**: When processing large
datasets, using streams to filter, analyze, and summarize data
can reduce boilerplate code and enhance clarity.
2. **Real-time Data Processing**: For scenarios where data
is continuously coming in (like a log file or sensor data),
streams can be beneficial for on-the-fly calculations or
transformations.
3. **Parallel Processing**: When working with large
collections on multicore processors, streams can simplify
parallelization without complex threading code.

10.Question
How can you think about the functional programming
aspects of streams?

Scan to Download
Answer:Streams leverage lambda expressions allowing you
to write more functional-style code. Operations like filter,
map, and reduce enable you to avoid side effects and focus
on the transformation of data, aligning closely with
functional programming principles.

Scan to Download
Chapter 7 | 5 Working with streams| Q&A
1.Question
How does the Streams API improve data processing
compared to traditional external iteration?
Answer:The Streams API facilitates internal
iteration, significantly simplifying data processing.
Instead of manually managing iteration, developers
can express complex queries like filtering or
mapping with concise, functional-style code. This
offers optimizations such as lazy evaluation and the
ability to execute in parallel, enhancing performance
and readability.

2.Question
What are the main operations supported by the Streams
API, and how do they benefit data manipulation?
Answer:The Streams API supports operations like filtering,
mapping, searching, and reducing data. Filtering allows
selective data retrieval based on criteria, mapping transforms
data into a new form, and reducing aggregates data into a

Scan to Download
single result (e.g., sum, max). These operations enable clean,
declarative data processing, enhancing maintainability.

3.Question
How can you optimize filtering in sorted streams using
takeWhile and dropWhile methods?
Answer:Using takeWhile and dropWhile on sorted streams
allows for efficiency by stopping the iteration as soon as the
predicate fails (takeWhile) or succeeds (dropWhile). This
means fewer elements are processed compared to a full filter
iteration, improving performance especially with large
datasets.

4.Question
What is the significance of the flatMap method in
processing streams, and when should you use it?
Answer:The flatMap method is essential for flattening nested
structures in streams; it allows mapping each element to a
stream and concatenating all resulting streams into a single
one. Use flatMap when you need to convert a stream of
collections or arrays into a single stream of their individual

Scan to Download
elements, enhancing usability in data transformations.

5.Question
Illustrate how Streams API handles uniqueness in data
retrieval using distinct operations.
Answer:By using the distinct method on a stream, you can
easily filter out duplicate elements based on their hashcode
and equality checks. For instance, if retrieving unique
numbers from a list, applying distinct directly removes any
duplicates, simplifying data manipulation.

6.Question
Explain the importance of reducing operations and
provide examples of common reductions.
Answer:Reducing operations combine elements in a stream
to produce a single value, crucial for aggregating data like
summing numbers or finding maximums. Examples include
using the reduce method to calculate the total of a list, or
employing built-in methods like max and sum directly on
specialized streams (IntStream). This reduces code
complexity and enhances performance.

Scan to Download
7.Question
Describe how the Streams API can create infinite streams
and the precautions that need to be taken.
Answer:The Streams API can generate infinite streams
through methods like iterate and generate, which produce
values on demand. However, precautions such as using the
limit method are essential to prevent unbounded processing
and ensure termination of operations, especially with infinite
data sources.

8.Question
What are the considerations for using stateful versus
stateless operations in streams?
Answer:Stateless operations like filter and map do not save
internal state, making them safe for parallel processing.
Conversely, stateful operations like sorted and distinct need
to maintain information across elements, which can lead to
resource inefficiencies and challenges in parallel execution.
Understanding these differences is crucial for optimizing
stream performance.

Scan to Download
9.Question
How does the Streams API enable creating streams from
various sources beyond collections?
Answer:The Streams API allows creating streams from static
values using Stream.of, from arrays via Arrays.stream, from
files through Files.lines, and even from functions using
iterate and generate. This versatility makes the Streams API
powerful for a wide range of data-processing scenarios.

10.Question
Can you provide an example of how to use numerical
streams effectively?
Answer:To effectively use numerical streams, for instance,
you can create an IntStream and perform operations like
summing values directly: int sum = IntStream.rangeClosed(1,
10).sum(); This avoids boxing issues typically associated
with Integer streams and allows using specialized methods
for numerical data handling.
Chapter 8 | 6 Collecting data with streams| Q&A
1.Question
What is the primary purpose of streams in Java 8, as

Scan to Download
described in this chapter?
Answer:Streams in Java 8 serve to process
collections of data through database-like operations,
allowing you to transform, filter, and perform
reductions on data in a functional style.

2.Question
What distinguishes intermediate operations from
terminal operations when working with streams?
Answer:Intermediate operations, like filter and map, set up a
pipeline without consuming the stream, whereas terminal
operations, like collect and reduce, consume the stream to
produce a final result.

3.Question
How does the collect method differ from the reduce
method in the context of streams?
Answer:The collect method is designed for mutating a
container to accumulate results, allowing mutable data
structures, while reduce focuses on immutability, combining
elements to produce a new value.

Scan to Download
4.Question
Can you explain the concept of collectors and how they
enhance data processing?
Answer:Collectors are recipes or strategies for accumulating
elements from a stream, providing reusable and flexible
methods, such as groupingBy for grouping or summingInt
for summarizing, thus enhancing clarity and maintainability
in data processing.

5.Question
What is the significance of the groupingBy collector in
stream operations?
Answer:The groupingBy collector allows for grouping
elements of a stream by a specific criterion, producing a map
where keys represent the grouping criteria, enabling complex
data organization with minimal code.

6.Question
Give an example of how to group and summarize data
using collectors. What is the output of this operation?
Answer:Using the groupingBy collector with summingInt,
you can group a list of dishes by type and sum their calorie

Scan to Download
content: Map<Dish.Type, Integer> totalCaloriesByType =
menu.stream().collect(groupingBy(Dish::getType,
summingInt(Dish::getCalories))); Output example would be
a map detailing total calories by dish type.

7.Question
What challenges did developers face before Java 8 when
grouping collections, and how does streams resolve these
issues?
Answer:Before Java 8, grouping collections involved verbose
and complex code with nested loops and conditionals. Java 8
streams provide a streamlined, readable syntax, allowing
grouping in a single, elegant statement.

8.Question
Describe how the customized collectors can improve
performance in specific scenarios, using examples from
the text.
Answer:Custom collectors, such as the
PrimeNumbersCollector, can improve performance by
allowing optimizations tailored to specific data processing
needs, like reducing the number of division operations

Scan to Download
needed to determine prime numbers, as demonstrated in the
performance comparison with predefined collectors.

9.Question
In what ways can collectors be combined to achieve
multifaceted data transformations?
Answer:Collectors can be nested or combined through
parameters, allowing for layered operations like multilevel
grouping and partitioning, enabling intricate data structures
and comprehensive summaries in fewer lines of code.

10.Question
What are some practical applications of the
partitioningBy collector?
Answer:The partitioningBy collector can be used to
categorize data into two groups, such as separating
vegetarian from non-vegetarian dishes or categorizing
numbers into prime and non-prime groups, aiding in clear
and efficient data categorization.
Chapter 9 | 7 Parallel data processing and
performance| Q&A
1.Question

Scan to Download
What are the benefits of using parallel streams in Java
for processing collections of data?
Answer:Parallel streams in Java allow developers to
process collections more efficiently by automatically
utilizing multiple CPU cores. This leads to improved
performance, especially for large datasets, as the
workload is distributed across available processors
without the need for manual thread management or
synchronization.

2.Question
How do parallel streams determine how to split the data
for processing?
Answer:Parallel streams utilize a mechanism called
Spliterator, which recursively splits the data into smaller
chunks that can be processed independently by different
threads. This is crucial for achieving efficient parallel
processing, as it enables tasks to be executed simultaneously.

3.Question
What should you keep in mind when deciding to use
parallel streams?

Scan to Download
Answer:Always measure performance differences between
sequential and parallel implementations. Also, be aware of
data structure characteristics to ensure optimal performance,
and avoid using parallel streams with operations that require
maintaining order.

4.Question
Why might a parallel stream underperform when used
improperly?
Answer:If the operations performed on a parallel stream
involve shared mutable state or depend on ordering, it can
lead to incorrect results and performance degradation. For
example, certain stream operations like 'iterate' are inherently
sequential and not suitable for parallel processing.

5.Question
What is the fork/join framework and how does it relate to
parallel streams?
Answer:The fork/join framework is a concurrent
programming framework in Java that supports parallel
processing by splitting tasks into smaller subtasks and

Scan to Download
combining their results. Parallel streams leverage this
framework to simplify task splitting and execution across
multiple threads.

6.Question
What are some best practices to ensure effective use of the
fork/join framework?
Answer:Avoid using the join method prematurely, optimize
the split decision to prevent excessive task creation, and
ensure subtasks are independent and sufficiently granular.
Also, run benchmarks multiple times to account for warm-up
and JIT optimizations.

7.Question
How can you implement your own Spliterator, and why
would you do it?
Answer:You might implement your own Spliterator to have
fine-grained control over how data is partitioned, particularly
when working with non-traditional data structures or specific
input constraints. For example, creating a Spliterator that
avoids splitting words in a string ensures the accuracy of

Scan to Download
operations like counting words.

8.Question
What are the drawbacks of parallel streams when
working with small datasets?
Answer:Parallel streams incur overhead that generally
outweighs the performance benefits when processing small
datasets. Therefore, using parallel streams is typically not
advantageous for operations on fewer items.

9.Question
How does the choice of data structure impact the
performance of parallel streams?
Answer:Choosing the right data structure is critical because
some data structures, like ArrayLists, split efficiently, while
others, like LinkedLists, do not. Using primitive streams also
eliminates boxing/unboxing overhead, improving
performance.

10.Question
What are the implications of using boxed types in parallel
streams?
Answer:Using boxed types in parallel streams can introduce

Scan to Download
performance penalties due to the overhead of boxing and
unboxing operations. It's advisable to use primitive streams
when available to mitigate this.

Scan to Download
Chapter 10 | 8 Collection API enhancements| Q&A
1.Question
How did Java 9 improve the process of creating collection
objects?
Answer:Java 9 introduced factory methods such as
List.of, Set.of, and Map.of which allow developers to
create immutable collection objects more
conveniently, reducing verbosity and the potential
for bugs. Instead of multiple lines of code to create a
collection, you can create them in a single line.

2.Question
What is the significance of immutable collections in Java
9?
Answer:Immutable collections protect against unintended
modifications, ensuring that once you create a collection, its
contents cannot be changed. This helps maintain the integrity
of data throughout the application's execution.

3.Question
Can you explain the removeIf method and its
advantages?

Scan to Download
Answer:The removeIf method provides a concise way to
remove elements from collections based on a given predicate.
It simplifies the process of removal, eliminating the risk of
ConcurrentModificationExceptions that arise when
modifying a collection during iteration.

4.Question
What benefits do the computeIfAbsent,
computeIfPresent, and compute methods bring to Map
operations?
Answer:These methods streamline operations where you
need to conditionally modify or compute values associated
with keys in a Map. They simplify caching, updating, and
handling cases where keys may not exist, minimizing
boilerplate code.

5.Question
Why should one use the forEach method introduced in
Java 8 for Map?
Answer:The forEach method simplifies the iteration over
keys and values of a Map, making the code more readable
and expressive. Instead of boilerplate iterator code, you can

Scan to Download
pass a lambda directly to perform actions on each entry.

6.Question
How does the merge method in Map operations enhance
flexibility?
Answer:The merge method allows you to combine values
associated with duplicate keys in a customizable way,
providing a built-in mechanism for handling conflicts when
combining Maps, thus reducing the complexity of the
merging logic.

7.Question
What is the primary purpose of the improved
ConcurrentHashMap in Java?
Answer:The improved ConcurrentHashMap facilitates
concurrent access by allowing multiple threads to perform
read and write operations simultaneously, thus enhancing
performance and scalability in a multi-threaded environment.

8.Question
Describe the significance of new default methods added to
the Map interface.
Answer:New default methods improve code conciseness by

Scan to Download
providing common functionality like replacing values,
iterating, and performing reductions without needing to
explicitly implement this logic, making it easier and less
error-prone to work with Maps.

9.Question
How do the enhancements in the Collection API reflect on
the developer's productivity?
Answer:The enhancements, such as factory methods and
streamlined operational methods, significantly shorten the
code needed for common tasks, reduce the potential for
errors, and encourage the use of more idiomatic, readable
patterns, thus boosting overall productivity.
Chapter 11 | 9 Refactoring, testing, and debugging|
Q&A
1.Question
How can using lambda expressions improve the
readability of code?
Answer:Lambda expressions allow for more concise
and compact code, reducing verbosity compared to
anonymous classes. They help express behavior

Scan to Download
parameterization, enabling the passing of different
behaviors as arguments, which can adapt to
changing requirements. This makes the code easier
to understand, especially when combined with
method references and the Streams API.

2.Question
What is the process of refactoring anonymous classes to
lambda expressions, and what difficulties might arise?
Answer:You can refactor an anonymous class, which
implements a single abstract method, into a lambda
expression to make the code more succinct. Challenges may
include differences in how 'this' is interpreted between
anonymous classes and lambdas, and potential ambiguity
when trying to pass a lambda expression to overloaded
methods expecting different types.

3.Question
In what scenarios should method references be preferred
over lambda expressions?
Answer:Method references should be used when the lambda

Scan to Download
expression simply calls an existing method, as they are more
readable and clearly convey the code's intent. For instance,
using Dish::getCaloricLevel is clearer than using a lambda
that replicates its logic.

4.Question
What is the main advantage of converting
imperative-style data processing to Streams API?
Answer:Using the Streams API clarifies the intent of data
processing by allowing for a functional approach to
operations like filtering and mapping, leading to cleaner and
more understandable code. It also facilitates optimizations
like parallel processing.

5.Question
How do lambda expressions enhance flexibility in code
design?
Answer:Lambda expressions enable behavior
parameterization, allowing you to represent different
behaviors as lambda instances which can be passed around.
This design aids in adapting to requirement changes, such as

Scan to Download
using different Predicates for filtering data.

6.Question
How can one test lambda expressions effectively?
Answer:Testing lambda expressions is tricky since they lack
names. Instead of testing the lambda directly, focus on
testing the behavior of the methods that use the lambdas. If
lambdas are stored in fields, you can test their behavior by
invoking the corresponding functional interface method
using different inputs.

7.Question
What debugging challenges might developers face when
working with lambda expressions?
Answer:Stack traces involving lambda expressions can be
confusing because they don't have clear names, making it
difficult to identify the source of an error. Developers may
encounter abstract names in the stack trace, which don't
provide intuitive context.

8.Question
What is the role of the 'peek' method in stream processing
for debugging?

Scan to Download
Answer:The 'peek' method allows you to perform an action
on each element in the stream without consuming it, which is
useful for debugging as it lets you log intermediate values
during the processing pipeline.

9.Question
How can lambda expressions alleviate boilerplate code in
design patterns?
Answer:Lambda expressions can replace verbose or
repetitive code structures found in design patterns like
Strategy or Template Method, allowing developers to define
behavior succinctly without the need for extra classes or
interfaces.

10.Question
What critical features should you consider when
implementing object-oriented design patterns using
lambda expressions?
Answer:When implementing design patterns like Strategy,
it's essential to ensure that functional interfaces are defined
appropriately to match the expected method signatures,
allowing for effective and clear use of lambda expressions.

Scan to Download
Chapter 12 | 10 Domain-specific languages using
lambdas| Q&A
1.Question
What is the main purpose of a domain-specific language
(DSL) in software development?
Answer:The main purpose of a DSL is to bridge the
gap between developers and domain experts,
allowing business logic to be expressed in a language
that non-developers can understand. This promotes
clear communication of intentions, making it easier
for domain experts to read and validate the business
rules.

2.Question
What are the benefits of using a DSL in a Java
application?
Answer:Benefits of using a DSL include improved code
conciseness and readability, maintainability, a higher level of
abstraction that aligns with business domains, greater focus
on business logic, and clearer separation of concerns between
business-related code and infrastructure.

Scan to Download
3.Question
How has Java 8 improved the possibilities for
implementing DSLs?
Answer:Java 8 introduced lambda expressions and method
references, which significantly reduce verbosity and improve
the expressiveness of code, making it easier to implement
compact and readable internal DSLs.

4.Question
What are the potential downsides of creating a DSL
within a software project?
Answer:Creating a DSL can be challenging and involves
upfront design costs, ongoing maintenance, and possible
learning curves for developers. Additionally, poorly designed
DSLs can lead to increased complexity and an additional
layer of indirection which might negatively impact
performance.

5.Question
What distinguishes between internal and external DSLs?
Answer:Internal DSLs are built within the host programming
language (like Java), utilizing its syntax and features, while

Scan to Download
external DSLs are independent languages specifically created
for a particular domain, requiring parsing and separate
runtime infrastructure.

6.Question
Can DSLs be combined, and if so, why would that be
beneficial?
Answer:Yes, DSLs can be combined to leverage the strengths
of multiple patterns, enhancing their usability and
expressiveness while allowing developers to create more
intuitive and flexible APIs that cater to various needs within
a domain.

7.Question
What are some examples of DSLs found in modern Java
APIs?
Answer:Examples of DSLs in modern Java include the
Stream API for collection processing and the Comparator
interface for sorting elements, both of which utilize method
chaining and lambda expressions for enhanced readability.

8.Question
How does the jOOQ library exemplify the use of a DSL in

Scan to Download
Java?
Answer:jOOQ provides a type-safe DSL for writing SQL
queries within Java. It allows developers to construct queries
in a fluent way while maintaining the safety of static type
checks, closely mimicking SQL syntax and improving
readability.

9.Question
What role does the Cucumber framework play in relation
to DSLs?
Answer:Cucumber is a Behavior-Driven Development
(BDD) framework that allows business scenarios to be
described in a structured DSL, enabling non-developers to
write executable specifications that align closely with
business requirements.

10.Question
Why is readability considered crucial in the context of
DSLs, especially related to business applications?
Answer:Readability is crucial because it allows both
technical and non-technical stakeholders to understand,

Scan to Download
validate, and communicate about the software, facilitating
better collaboration and ensuring that the implementation
aligns with business expectations.

Scan to Download
Chapter 13 | 11 Using Optional as a better
alternative to null| Q&A
1.Question
What is the main problem with using null references in
Java?
Answer:Using null references can lead to
NullPointerExceptions, which are one of the most
common runtime errors in Java. This also results in
bloated code as developers add numerous null
checks, making the code less readable and
maintainable.

2.Question
How did Tony Hoare, the creator of the null reference
concept, describe his decision?
Answer:Tony Hoare referred to the introduction of null
references as 'my billion-dollar mistake,' acknowledging that
while it was easy to implement, it caused significant
programming challenges and errors over time.

3.Question
What is the recommended alternative to using null

Scan to Download
references in Java?
Answer:The recommended alternative is to use the Optional
class (java.util.Optional<T>) introduced in Java 8, which
safely encapsulates the presence or absence of a value.

4.Question
Why is using Optional better than null?
Answer:Using Optional provides a clear and type-safe way to
indicate that a variable may not have a value, thus avoiding
NullPointerExceptions. It also encourages developers to
handle missing values explicitly through the API design.

5.Question
What does the map method of Optional do?
Answer:The map method applies a function to the value
contained in the Optional if it is present, returning an
Optional containing the result. If the Optional is empty, it
returns an empty Optional.

6.Question
How does flatMap differ from map in the context of
Optionals?

Scan to Download
Answer:flatMap allows you to apply a function that returns
another Optional, effectively flattening the nested Optional
structure. In contrast, map simply wraps the result in an
Optional, potentially resulting in an Optional of an Optional.

7.Question
What is the purpose of the filter method in Optional?
Answer:The filter method allows you to conditionally filter
the value inside an Optional based on a predicate. If the value
is present and matches the predicate, it remains unchanged;
otherwise, it returns an empty Optional.

8.Question
How do you create an Optional object from a potentially
null value?
Answer:You can create an Optional from a potentially null
value using the static factory method
Optional.ofNullable(value), which returns an empty Optional
if the value is null.

9.Question
What is a common pattern for handling default values
with Optional?

Scan to Download
Answer:You can use the orElse() method to provide a default
value that is returned if the Optional is empty. For example,
optionalValue.orElse(defaultValue) will return defaultValue if
optionalValue is empty.

10.Question
What is a practical use case for using Optional in your
domain model?
Answer:Using Optional helps clarify your domain model by
explicitly indicating which fields may or may not have valid
values. For instance, if a person may not own a car, you
would declare the car field as Optional<Car> instead of Car.
Chapter 14 | 12 New Date and Time API| Q&A
1.Question
Why was a new Date and Time API introduced in Java 8?
Answer:The previous date and time support in Java
(specifically java.util.Date and java.util.Calendar)
had numerous flaws, including poor usability,
confusion over which class to use, and design issues
such as having mutable classes and inconsistent

Scan to Download
month indexes. The new API aims to provide a more
robust, user-friendly, and comprehensive solution
for handling dates and times.

2.Question
What are the main classes introduced in the new Date and
Time API?
Answer:The main classes introduced in the new API include
LocalDate, LocalTime, LocalDateTime, Instant, Duration,
and Period. Each class serves a specific purpose, such as
representing a date without a time zone (LocalDate) or a
precise moment in time (Instant).

3.Question
How do LocalDate and LocalTime differ from Instant in
the new API?
Answer:LocalDate and LocalTime are meant for
human-readable date and time representation and do not
carry any timezone information. In contrast, Instant is
designed for machine use, representing a point on a
continuous timeline as the number of seconds and

Scan to Download
nanoseconds since the Unix epoch (January 1, 1970 UTC).

4.Question
What is the significance of immutability in the Date and
Time API?
Answer:Immutability ensures that date and time objects
cannot be altered once created, promoting a functional
programming style, making the code safer from bugs related
to unexpected changes, ensuring thread safety, and
preserving the integrity of the domain model.

5.Question
Can you explain how to manipulate dates in the new API?
Answer:Dates can be manipulated in two primary ways:
absolutely (changing specific attributes like year, month, or
day) using methods like withYear(), and relatively (adding or
subtracting time) using methods like plusDays() or
minusMonths(). Both methods return a new instance with the
changes applied, preserving the original date object.

6.Question
What are TemporalAdjusters, and how are they used?
Answer:TemporalAdjusters are special operations that allow

Scan to Download
for complex date adjustments, like moving to the next
Sunday or the first day of the month. They can be predefined
or custom-made, making it simple to apply sophisticated date
manipulations without rewriting code.

7.Question
How does the new API handle time zones?
Answer:The new API introduces the ZoneId class to replace
the outdated TimeZone class. This new class simplifies
working with time zones and their complexities, such as
Daylight Saving Time. You can obtain a ZoneId through a
region ID and use it to create ZonedDateTime instances that
represent both the date and time along with the associated
time zone.

8.Question
What is the purpose of the DateTimeFormatter class?
Answer:DateTimeFormatter is used for formatting and
parsing date and time objects. It allows you to create output
strings in specific formats and convert strings back into date
objects, providing a more reliable and thread-safe alternative

Scan to Download
to the old java.util.DateFormat.

9.Question
What should developers generally prefer when dealing
with dates in Java?
Answer:Developers are advised to use LocalDate for most
date operations to avoid assumptions about month lengths
and the structure of calendars when dealing with
multi-calendar systems. The new API supports alternative
calendars, but LocalDate is preferred for its simplicity and
compatibility.

10.Question
Can you create custom TemporalAdjusters? If so, how?
Answer:Yes, custom TemporalAdjusters can be created by
implementing the TemporalAdjuster interface, which
requires defining the adjustInto method that dictates how to
adjust a given temporal object. This can also be done using
lambda expressions for more concise code.

11.Question
What are some of the alternative calendar systems
supported by the Date and Time API?

Scan to Download
Answer:The API supports several alternative calendar
systems, including ThaiBuddhistDate, MinguoDate,
JapaneseDate, and HijrahDate, all of which implement the
ChronoLocalDate interface, allowing for localized date
representations.
Chapter 15 | 13 Default methods| Q&A
1.Question
What problem do default methods in Java 8 solve for
library designers?
Answer:Default methods allow library designers to
evolve interfaces without requiring existing classes
to be modified. They provide a
backward-compatible way to add new functionality
to interfaces, as implementing classes automatically
inherit the default implementations unless
overridden.

2.Question
How do default methods differ from traditional methods
in interfaces?

Scan to Download
Answer:Traditional interface methods required all
implementing classes to provide an implementation, which
could lead to breaking changes if the interface was updated.
Default methods, on the other hand, allow interfaces to
provide default implementations, meaning implementing
classes do not have to override them unless necessary.

3.Question
Can you give a specific example of a default method in the
Java API?
Answer:A well-known example is the 'sort' method in the
List interface. Defined as 'default void sort(Comparator<?
super E> c)', this method allows lists to be sorted without
requiring all implementing classes to implement their own
version of 'sort'.

4.Question
What are the three resolution rules for method conflicts
in Java interfaces with default methods?
Answer:1. Classes always win: A method declaration in the
class takes priority over default method declarations. 2.

Scan to Download
Subinterfaces win: If there is a conflict, the method defined
in the most specific interface is chosen. 3. Explicit
disambiguation: If both methods are equally specific and
cause ambiguity, the implementing class must explicitly
override the method to avoid compile errors.

5.Question
What is one benefit of using private methods in interfaces
starting from Java 9?
Answer:Private methods in interfaces allow code to be shared
among default methods within the same interface, reducing
redundancy and promoting cleaner, more maintainable code.

6.Question
Why were default methods introduced into Java?
Answer:Default methods were introduced to help manage the
evolution of APIs and to allow interfaces to provide
additional functionality without disrupting existing
implementations, thereby addressing compatibility issues that
arise from modifying published interfaces.

7.Question
How can default methods help reduce boilerplate code in

Scan to Download
Java?
Answer:Default methods can provide standard
implementations for optional methods that previously
required empty implementations in concrete classes, such as
the 'remove' method in the Iterator interface, thus reducing
the amount of boilerplate code developers must write.

8.Question
What impact do default methods have on the concept of
multiple inheritance in Java?
Answer:With default methods, Java allows classes to inherit
default behavior from multiple interfaces without the
complications of traditional multiple inheritance, effectively
enabling code reuse while still maintaining the single
inheritance model for classes.

9.Question
What would happen if a class implements two interfaces
with the same default method signature?
Answer:If a class implements two interfaces that provide the
same default method, the Java compiler will produce an error

Scan to Download
due to ambiguity. The class must explicitly override the
method and choose which default method implementation to
use.

10.Question
What is the advantage of minimal interfaces when using
default methods?
Answer:Minimal interfaces lead to better design by keeping
interfaces focused and orthogonal, which aids in achieving
greater code reuse and allows for the composition of
behaviors across different classes without unnecessary
complexity.

Scan to Download
Chapter 16 | 14 The Java Module System| Q&A
1.Question
What is the main purpose of the Java Module System
introduced in Java 9?
Answer:The Java Module System aims to improve
code maintainability and readability by promoting
modularity. It allows developers to group code into
distinct modules, each with clear dependencies and
encapsulation, thereby making it easier to manage
complex applications.

2.Question
How does separation of concerns benefit software
development?
Answer:Separation of concerns allows developers to
decompose applications into distinct modules that handle
specific functionalities. This leads to better teamwork, easier
maintenance, and enhances code reusability because
individual modules can be developed and tested in isolation.

3.Question
Why is information hiding crucial in software design?

Scan to Download
Answer:Information hiding protects the internal workings of
a module, reducing the risk of unintended side effects when
changes are made. By preventing external components from
relying on internal details, it allows for greater flexibility in
updating and refactoring code.

4.Question
What limitations existed in Java before the introduction
of the Module System?
Answer:Prior to Java 9, the lack of fine-grained control over
package visibility and the reliance on a flat classpath made
dependency management difficult. This led to issues like
'Class Path Hell', where conflicts and versioning problems
arose, complicating application development.

5.Question
How does the module descriptor (module-info.java)
function in the Java Module System?
Answer:The module descriptor defines a module's name, its
dependencies (using requires clauses), and which packages
are accessible to other modules (using exports clauses). This

Scan to Download
structured approach enhances encapsulation and clarity in
module relationships.

6.Question
What are automatic modules and how do they operate
within the Java Module System?
Answer:Automatic modules are JAR files that do not include
a module descriptor but are placed on the module path. They
automatically export all their packages, allowing for
seamless integration of legacy libraries with the new module
system.

7.Question
How can developers manage dependencies between
modules effectively?
Answer:Developers can use the requires clause in the module
descriptor to specify dependencies. This ensures that any
required modules are available at both compile-time and
runtime, allowing for better control and cooperation between
different parts of an application.

8.Question
What is the significance of Maven in relation to the Java

Scan to Download
Module System?
Answer:Maven provides tools to manage projects structured
with the Java Module System, including handling module
dependencies, compiling modules independently, and
ensuring that the correct module paths are set for building
and running applications.

9.Question
What is the impact of the Java Module System on the
Java Development Kit (JDK)?
Answer:The Java Module System allows for the
modularization of the JDK itself, reducing the size of
applications by enabling developers to include only the
necessary modules, and thus improving maintenance and
reducing dependencies on unnecessary classes.

10.Question
Can you explain the relationship between modules and
their naming conventions?
Answer:Modules should ideally follow a naming convention
that uses the reverse internet domain format, similar to

Scan to Download
packages. This approach provides a clear hierarchy and
prevents naming conflicts, improving organization within the
codebase.
Chapter 17 | 15 Concepts behind
CompletableFuture and reactive programming|
Q&A
1.Question
What are the two major trends forcing developers to
rethink how software is written?
Answer:The first trend is the rise of multicore
processors, which drives the need for software that
efficiently uses parallelism. The second trend is the
growing use of Internet services and microservices
architectures, necessitating better coordination and
interaction between multiple services.

2.Question
How has Java evolved in terms of concurrency support
over the years?
Answer:Java's concurrency support has evolved from basic
thread manipulation with locks and synchronized methods to

Scan to Download
more advanced features like the ExecutorService, Future and
CompletableFuture interfaces, and reactive programming
support in Java 9, reflecting the increasing demand for
effective programming on multicore machines.

3.Question
In what ways do CompletableFuture and the Java 9 Flow
API enhance programming with concurrency?
Answer:CompletableFuture enables the composition of
asynchronous tasks without blocking, thus enhancing
efficiency. The Java 9 Flow API introduces a reactive
programming model based on the publish-subscribe pattern
that allows for handling streams of data and events in a more
dynamic and responsive manner.

4.Question
What is the box-and-channel model and how is it useful in
concurrent programming?
Answer:The box-and-channel model is a visual
representation that helps to conceptualize and structure
concurrent operations by treating computations as boxes that

Scan to Download
communicate with each other over channels. This model
simplifies the understanding of how tasks can be executed
concurrently and how data flows through a system.

5.Question
What are the main differences between synchronous and
asynchronous APIs in Java?
Answer:Synchronous APIs block the calling thread until a
result is available, while asynchronous APIs allow a method
to return immediately and handle the result later, enabling
better resource utilization and responsiveness in applications.

6.Question
What role does backpressure play in the reactive
programming model in Java?
Answer:Backpressure is a flow control mechanism that
enables subscribers to regulate the rate of incoming messages
from publishers, preventing overload and ensuring that
subscribers can process events at their own pace.

7.Question
Why is it important to avoid blocking operations in a
multithreaded environment?

Scan to Download
Answer:Blocking operations consume valuable threads that
could be executing other tasks, leading to inefficient use of
resources and potential bottlenecks in application
performance, especially when many tasks are involved.

8.Question
How does reactive programming differ from traditional
concurrent programming models?
Answer:Reactive programming focuses on data streams and
the asynchronous handling of multiple results over time,
whereas traditional models typically involve one-shot
computation with tasks that run to completion. Reactive
programming allows for more dynamic interaction and
responsiveness.

9.Question
Describe a scenario where using asynchronous
programming can significantly improve application
performance.
Answer:An example scenario is when an application needs to
fetch data from multiple APIs simultaneously. By using
asynchronous programming, the application can initiate

Scan to Download
requests to all APIs at once and handle each response as it
arrives, instead of waiting for each request to complete
before making the next one. This reduces overall wait time
and enhances user experience.

10.Question
What are the benefits of using the CompletableFuture
class over traditional Future implementations in Java?
Answer:The CompletableFuture class allows for
non-blocking asynchronous computations, chaining multiple
tasks together, and handling exceptions more gracefully. It
supports combinators that make it easier to express complex
workflows without blocking threads, leading to better
performance and resource management.
Chapter 18 | 16 CompletableFuture: composable
asynchronous programming| Q&A
1.Question
What is the primary benefit of using the
CompletableFuture API in Java?
Answer:CompletableFuture provides a way to write
non-blocking, asynchronous code that allows

Scan to Download
multiple tasks to be performed concurrently. It
simplifies error handling, chaining tasks, and
combines results from multiple asynchronous
operations.

2.Question
How does the CompletableFuture class enhance the
Future interface?
Answer:CompletableFuture extends Future by adding
methods that allow for more complex asynchronous
programming patterns, such as combining tasks and reacting
to their completion without blocking the main executing
thread.

3.Question
What are some key advantages of using an asynchronous
API over a synchronous one?
Answer:Asynchronous APIs improve application
responsiveness and performance by allowing other tasks to
run while waiting for external processes to complete,
reducing idle time and making better use of system

Scan to Download
resources.

4.Question
What strategy can be used to handle potential exceptions
in asynchronous computations?
Answer:Using the completeExceptionally method of
CompletableFuture allows you to propagate exceptions from
a background computation to the calling context, making it
easier to handle errors.

5.Question
How can executing multiple asynchronous tasks
concurrently affect performance compared to sequential
execution?
Answer:Executing tasks concurrently can significantly
reduce overall execution time, especially when tasks involve
waiting for external resources, as it allows for better
utilization of system resources and reduces bottlenecks.

6.Question
What is the role of the thenCompose method in
CompletableFuture?
Answer:The thenCompose method allows for sequencing

Scan to Download
two asynchronous operations, where the second operation is
dependent on the result of the first, enabling a clean and
manageable way to chain together asynchronous tasks.

7.Question
What is the importance of using a custom Executor with
CompletableFutures?
Answer:Using a custom Executor allows you to configure the
number of threads used for executing tasks, optimizing
performance based on the application's specific workload and
system capabilities.

8.Question
How can you ensure timeouts in asynchronous
computations when using CompletableFuture?
Answer:Java 9 introduces the orTimeout and
completeOnTimeout methods, which enable you to specify
timeouts for CompletableFutures, allowing you to manage
long-running tasks effectively.

9.Question
In what scenario would you prefer to use
CompletableFutures over parallel streams?

Scan to Download
Answer:If your tasks involve waiting for I/O operations or
other resource-intensive actions, CompletableFutures provide
better control and flexibility to manage concurrent execution
without blocking.

10.Question
What is the benefit of using the allOf and anyOf methods
in CompletableFutures?
Answer:The allOf method allows you to wait for all the
CompletableFutures to complete, while anyOf allows you to
react as soon as one of the CompletableFutures completes,
enabling both aggregated and independent handling of
asynchronous results.

Scan to Download
Chapter 19 | 17 Reactive programming| Q&A
1.Question
What are the key principles highlighted by the Reactive
Manifesto in reactive programming?
Answer:The key principles highlighted by the
Reactive Manifesto include: 1. Responsive: Reactive
systems must have fast and predictable response
times, increasing user confidence. 2. Resilient: They
should remain responsive even in the face of
failures, utilizing techniques like replication and
decoupling components. 3. Elastic: Reactive systems
can react to different workloads and adjust resource
allocation automatically. 4. Message-driven:
Communication between components should occur
through asynchronous messages to ensure loose
coupling and location transparency.

2.Question
How does reactive programming address the challenges
posed by modern applications?

Scan to Download
Answer:Reactive programming addresses the challenges of
modern applications, which need to handle big data
efficiently, operate in heterogeneous environments, and meet
user expectations for low latency. By enabling asynchronous
processing of data streams from various sources, reactive
programming enhances responsiveness and throughput,
making it suitable for contemporary demands such as IoT
traffic and mobile application performance.

3.Question
Why is backpressure important in reactive
programming?
Answer:Backpressure is important because it allows slow
consumers to control the flow of data from faster producers,
preventing overwhelming situations that could lead to data
loss or system crashes. This mechanism ensures that every
component in a reactive system operates within its capacity,
maintaining system reliability and performance.

4.Question
What advantages does reactive programming offer in
terms of application structure and resources?

Scan to Download
Answer:Reactive programming permits more efficient use of
resources by allowing non-blocking operations, which
maximizes CPU utilization. This approach decreases the
complexity associated with traditional multi-threading, such
as synchronization and race conditions, allowing developers
to focus on business logic instead of low-level
implementation details.

5.Question
How do processors in a reactive system function, and
what role do they play?
Answer:Processors in a reactive system act as both
subscribers and publishers. They transform data as it flows
through the reactive stream. A processor can take input from
another publisher, apply some transformation, and emit the
modified data to its subscribers, allowing for sophisticated
data manipulation and stream processing.

6.Question
Why are there no default implementations of the Flow
API in Java 9, and what does this mean for developers?

Scan to Download
Answer:Java 9 provides only the Flow API interfaces but no
default implementations to encourage existing libraries like
RxJava and Akka to adapt and validate their reactive
concepts against a standard. This means developers are
encouraged to utilize these libraries to take full advantage of
reactive programming capabilities rather than implementing
everything from scratch.

7.Question
Describe a practical example of how events are processed
in RxJava. How does it improve the user experience?
Answer:In RxJava, events can be processed asynchronously
using observables. For instance, fetching the temperature at a
set interval and displaying it in real-time enhances user
experience by providing live updates with minimal latency.
This arrangement prevents the UI from freezing during data
retrieval, ensuring smooth user interactions.

8.Question
What are marble diagrams, and how do they assist in
understanding reactive programming concepts?

Scan to Download
Answer:Marble diagrams are a visual representation of the
flow of data in reactive streams. They convey how operators
transform and combine streams using geometric shapes,
making complex behaviors easier to understand compared to
textual descriptions. They help both developers and
stakeholders quickly grasp the functional aspects of reactive
operations.

9.Question
How does the use of external libraries like RxJava enrich
reactive programming compared to using the native Flow
API?
Answer:External libraries like RxJava enrich reactive
programming by providing a richer set of operators to create,
manipulate, and transform streams beyond the basic
functionalities of the Flow API. They offer built-in features
for combining multiple streams, filtering data, and error
handling, enhancing the development efficiency and
functionality of reactive applications.
Chapter 20 | 18 Thinking functionally| Q&A

Scan to Download
1.Question
What are the core principles of functional programming
as discussed in the chapter?
Answer:The core principles of functional
programming include:
1. Side Effects: A function should be side-effect free,
meaning it does not modify any state outside of its
scope.
2. Immutability: Objects should not change state
after their creation, enhancing predictability and
safety in concurrent environments.
3. Declarative Programming: This style focuses on
what to do rather than how to do it, allowing
programmers to express logic without specifying
control flow.
4. Referential Transparency: Functions should
return the same result for the same input, which
simplifies reasoning about code.

2.Question

Scan to Download
How does avoiding mutable shared data impact software
maintenance?
Answer:Avoiding mutable shared data structures simplifies
maintenance because it reduces unexpected behaviors when
different parts of a program modify the same data. Without
shared mutable states, each part of the program can work
independently, making it easier to understand and trace the
origins of bugs, leading to more reliable and maintainable
code.

3.Question
Can you explain the difference between functional-style
programming and pure functional programming?
Answer:Functional-style programming allows the use of
non-functional mechanisms under certain restrictions, such as
mutating local variables or using side-effecting library
functions that are hidden from the caller. Pure functional
programming, in contrast, strictly prohibits side effects and
focuses on writing functions that are referentially transparent
and independent from external states.

Scan to Download
4.Question
What is declarative programming and how does it relate
to functional programming?
Answer:Declarative programming emphasizes describing
what the program should accomplish without explicitly
detailing how to execute it. This contrasts with imperative
programming, which describes control flow in terms of
commands. Functional programming is a subset of
declarative programming, focusing on expressing
computations as mathematical functions and avoiding
mutable state.

5.Question
What role does recursion play in functional programming
according to the chapter?
Answer:Recursion is a fundamental technique in functional
programming that allows functions to call themselves,
promoting a what-to-do style of programming and
eliminating the need for iteration constructs that encourage
mutation. It aligns with the functional programming goal of

Scan to Download
maintaining immutability and promotes cleaner and more
expressive code.

6.Question
What is tail recursion and why is it preferred in
functional programming?
Answer:Tail recursion is a recursive form where the recursive
call is the last action in the function. This allows compilers to
optimize the recursion by reusing stack frames instead of
creating new ones for each call, thus preventing stack
overflow issues and improving performance. While Java
does not support tail-call optimization, using tail recursion
can still encourage better practices by making intent clear
and potential optimizations easier.

7.Question
How can embracing functional programming concepts
transform software development in Java?
Answer:Embracing functional programming concepts can
lead to writing cleaner, more modular, and maintainable code
in Java. It allows developers to leverage features like parallel

Scan to Download
processing through streams without the complexities of
locking and shared state management. This shift can increase
efficiency, enhance code readability, and make it easier to
reason about the behavior of applications.

8.Question
What practical problem-solving example illustrates
functional-style programming?
Answer:The chapter presents the problem of generating all
subsets of a list. By utilizing a recursive approach, students
can construct these subsets functionally, showcasing the
elegance of functional programming where the focus is on
defining what the result should look like rather than on how
to iteratively build it.
Chapter 21 | 19 Functional programming
techniques| Q&A
1.Question
What are first-class functions and how do they enhance
programming in Java?
Answer:First-class functions are functions that can
be treated like any other variable, meaning they can

Scan to Download
be passed as arguments, returned from other
functions, and stored in data structures. In Java,
this enhances programming by enabling more
flexible and reusable code through the use of method
references and lambda expressions introduced in
Java 8.

2.Question
Can you explain higher-order functions with an example?
Answer:Higher-order functions are those that can take other
functions as arguments or return functions as results. For
instance, in Java 8, the method 'Comparator.comparing' takes
a function as a parameter and returns a comparator. This
allows us to sort collections flexibly.

3.Question
What is currying and why is it useful?
Answer:Currying is a functional programming technique that
transforms a function taking multiple arguments into a series
of functions each taking a single argument. It enables greater
modularization and reuse of code. For example, a conversion

Scan to Download
function can be curried to create specialized converters for
specific pairs of units.

4.Question
What are persistent data structures and how do they
differ from mutable structures?
Answer:Persistent data structures are data structures that
preserve their previous versions when modified, meaning
that they cannot be changed once created. This prevents side
effects, which are common with mutable structures,
enhancing reliability and predictability in programming.

5.Question
How does lazy evaluation improve efficiency in
programming?
Answer:Lazy evaluation defers the computation of values
until they are explicitly needed, reducing unnecessary
calculations and resource consumption. For instance, streams
in Java perform operations on data only when a terminal
operation is called, which optimizes performance in
processing large datasets.

Scan to Download
6.Question
Describe pattern matching and its advantages over
traditional methods like 'if-then-else'.
Answer:Pattern matching allows for a more concise and
expressive way to destructure and handle data types, such as
trees, without cluttering the code with multiple 'if-then-else'
statements. It leads to cleaner and more maintainable code,
especially when working with complex data structures.

7.Question
What is the significance of referential transparency in
functional programming?
Answer:Referential transparency refers to the property of
functions where the output is determined solely by its input
values, without side effects. This allows functions to be
replaced with their outputs without changing the program's
behavior, which is important for building reliable and
maintainable software.

8.Question
How do combinators function in functional
programming?

Scan to Download
Answer:Combinators are functions that take other functions
as inputs and return a new function. This concept enhances
functional programming by enabling the construction of
complex operations through simpler building blocks. For
example, a function can be defined to combine multiple
functions together to create complex behavior.

Scan to Download
Chapter 22 | 20 Blending OOP and FP: Comparing
Java and Scala| Q&A
1.Question
What are the main advantages of using Scala over Java
for functional programming?
Answer:Scala provides a more sophisticated type
system, type inference, pattern matching, and
features like first-class functions. Additionally, it
allows for cleaner syntax, enabling more concise and
readable code compared to Java.

2.Question
How does Scala's approach to immutability differ from
Java's?
Answer:In Scala, collections such as Lists and Sets are
immutable by default, meaning they cannot be changed once
created. Updates create new collections instead of modifying
existing ones, which reduces data dependencies and
confusion. Java offers unmodifiable collections, but they are
wrappers over modifiable collections, which can still be
changed.

Scan to Download
3.Question
What is a trait in Scala and how does it compare to
interfaces in Java?
Answer:A trait is Scala's equivalent of Java interfaces, but it
can contain both abstract methods and default
implementations. Traits can also have mutable fields,
allowing for greater flexibility than Java's interfaces, which
cannot have state.

4.Question
What is the significance of first-class functions in Scala?
Answer:First-class functions in Scala mean that functions can
be passed as parameters, returned from other functions, and
stored in variables. This allows for a higher level of
abstraction and flexibility in functional programming.

5.Question
Can you explain currying in Scala and its benefits?
Answer:Currying in Scala allows you to break down a
function that takes multiple arguments into a series of
functions, each accepting a single argument. This enables
reusability and more straightforward partial application of

Scan to Download
functions, which can be very useful in functional
programming.

6.Question
How do collections in Scala support functional-style
operations?
Answer:Scala collections support operations such as map and
filter similar to Java's Stream API. The syntax in Scala is
concise, allowing for elegant and expressive data
manipulation.

7.Question
What can traits do that normal Java interfaces cannot?
Answer:Traits can have fields and provide default method
implementations, and they support multiple inheritance of
behaviors. This is unlike Java interfaces, which cannot
contain state and require explicit implementations for all
methods.

8.Question
How does Scala handle variables in closures compared to
Java?
Answer:In Scala, closures can capture and modify non-local

Scan to Download
variables directly, allowing for greater flexibility. In Java,
lambda expressions cannot modify the state of local variables
as they must be final or effectively final.

9.Question
What are tuples in Scala, and why are they beneficial?
Answer:Tuples in Scala allow for grouping multiple values
without creating a new class for each combination. This
makes the code more concise and expressive, enhancing
readability and reducing boilerplate code.

10.Question
Why is understanding Scala beneficial for Java
developers?
Answer:Learning Scala broadens a Java developer's
perspective on functional programming concepts and
practices, exposing them to a more extensive programming
language ecosystem, which can enhance their development
skills and adaptability.
Chapter 23 | 21 Conclusions and where next for
Java| Q&A
1.Question

Scan to Download
What has been the evolutionary effect of Java 8 features
on programming style?
Answer:Java 8 introduced functional-style
programming features that allow developers to
express ideas more succinctly and powerfully. The
support for lambdas and streams encourages a
programming style that focuses on immutability and
parallel processing, moving the center of gravity
from traditional imperative paradigms to a more
functional approach.

2.Question
Why is behavior parameterization important in Java?
Answer:Behavior parameterization, through the use of
lambdas and method references, allows developers to pass
chunks of code as parameters, making their code more
reusable and concise. This mechanism simplifies common
tasks like filtering collections, which previously required
cumbersome class structures.

3.Question

Scan to Download
How do streams improve the handling of collections in
Java?
Answer:Streams allow for a more efficient processing of
collections by enabling pipeline operations that are executed
in a single traversal. This reduces overhead and improves
performance, especially with large datasets, by optimizing
memory cache usage and making it easier to process data in
parallel.

4.Question
What is the significance of the Java 9 module system?
Answer:The Java 9 module system provides a way to
encapsulate components better, enhancing security and
maintainability. It introduces strong encapsulation of
packages, allows for clearer definition of module boundaries,
and supports the deployment of smaller parts of the Java
runtime, which is beneficial for modern, containerized
applications.

5.Question
How does Java 10's local variable type inference improve

Scan to Download
code readability?
Answer:Java 10 allows developers to use the 'var' keyword,
enabling the compiler to infer the type of a variable from its
initializer. This reduces boilerplate code and enhances
readability, making it easier to understand complex variable
types at a glance.

6.Question
What are some potential future enhancements for Java
mentioned in the chapter?
Answer:Future Java enhancements may include
declaration-site variance for generics to simplify type
handling, pattern matching for concise conditional logic, and
better integration of value types to improve efficiency and
immutability without compromising on existing backward
compatibility.

7.Question
Why is a shorter development cycle for Java significant?
Answer:A six-month development cycle allows Java to
evolve more quickly and remain competitive against

Scan to Download
emerging languages. This ensures that minor improvements
and features can be incorporated without being delayed by
larger changes, keeping the language relevant in a fast-paced
technology landscape.

8.Question
In what ways do Java 11 and future versions continue to
embrace functional programming?
Answer:Java 11 introduces features like enhanced switch
expressions and a new asynchronous HTTP client library that
leverage CompletableFutures. This indicates ongoing
integration of functional programming concepts, enhancing
Java's concurrency capabilities and making it more aligned
with modern programming paradigms.

9.Question
What key lesson can be drawn from the evolution of Java
8 to Java 11 as presented in the chapter?
Answer:The evolution from Java 8 to Java 11 highlights the
importance of adapting and embracing new programming
methodologies. It signifies a shift towards more

Scan to Download
functional-style programming and modular architectures,
ensuring Java remains a powerful and relevant language for
building robust applications.
Chapter 24 | A.1 Annotations| Q&A
1.Question
What are some key benefits of using annotations in Java?
Answer:Annotations in Java provide several
benefits, including enhancing code readability and
maintainability. They allow developers to decorate
code elements with metadata that can be queried at
runtime or compile-time. For instance, JUnit uses
annotations to mark test methods, making it clear
which methods should be executed in testing.
Annotations can also support documentation and
can help the Java compiler identify errors or
warnings, thus reducing bugs in the code.

2.Question
How have repeated annotations improved upon earlier
Java versions?

Scan to Download
Answer:In previous versions of Java, developers were
limited to apply only one annotation of a specific type per
declaration, which often led to cumbersome workarounds.
With Java 8, repeated annotations allow multiple usages of
the same annotation type without requiring additional idioms
like container annotations, streamlining code usage and
enhancing clarity.

3.Question
Can you provide an example of how to implement a
repeatable annotation?
Answer:To make an annotation repeatable in Java 8, you
must follow two steps: first, annotate the original annotation
with @Repeatable, specifying a container type; second,
create the container annotation. For example, to create a
repeatable @Author annotation:

@Repeatable(Authors.class)
@interface Author { String name(); }
@interface Authors { Author[] value(); }

Scan to Download
Then you can annotate a class like this:

@Author(name="Raoul")
@Author(name="Mario")
@Author(name="Alan")
class Book {}

4.Question
What is the significance of type annotations introduced in
Java 8?
Answer:Type annotations in Java 8 allow developers to
attach annotations to any type use, such as variables and
generics, extending the expressiveness of how code behaves.
For instance, using @NonNull in 'List<@NonNull Car> cars'
can help avoid null-related errors and ensure short-circuiting
logic during type checks. This capability aids in static
analysis, reducing runtime issues.

5.Question
What type of programming analysis can be facilitated by
the use of type annotations?

Scan to Download
Answer:Type annotations can facilitate program analysis by
allowing tools to check contracts on data types, enhancing
code quality. For example, if a method's parameter is marked
with a @NonNull annotation, analysis tools can statically
ensure that the method does not receive null values,
consequently minimizing potential null pointer exceptions at
runtime.

6.Question
Why is the @Repeatable annotation considered syntactic
sugar?
Answer:When using the @Repeatable annotation, it allows
developers to write cleaner code without the need for verbose
container annotations. This simplicity enhances readability
and reduces boilerplate code, as the underlying structure is
automatically managed by the compiler, essentially wrapping
multiple annotations in a single container seamlessly.

7.Question
How do annotations enhance documentation in Java
coding practices?

Scan to Download
Answer:Annotations such as @Deprecated serve as inline
documentation, clearly indicating to developers which
methods or classes should be avoided, along with
suggestions for alternatives when available. This feature
makes it easier to maintain and navigate through the code,
especially in collaborative environments.

8.Question
What changes in the Java 8 language updates might a
Java developer find most impactful?
Answer:Java 8 brought significant enhancements, especially
with the introduction of repeated annotations and type
annotations. These changes not only simplify how
annotations are used but also improve type safety and code
quality through clearer contracts on data usage, making them
a vital part of improving Java’s usability and maintainability.

Scan to Download
Chapter 25 | A.2 Generalized target-type inference|
Q&A
1.Question
What is the significance of the Checker framework in
Java 8?
Answer:The Checker framework enhances type
checking in Java 8 by allowing the use of various
type annotations. Though Java 8 does not come with
built-in annotations for this purpose, the Checker
framework provides a solution to enforce stricter
type constraints, ensuring that developers can catch
more potential errors at compile time.

2.Question
How has type inference been improved in Java 8
compared to previous versions?
Answer:Java 8 improves type inference by enabling more
flexible handling of generic types. Previously, developers
needed to explicitly specify the type when calling generic
methods, but now, Java 8 allows the compiler to infer the
correct type from the context, making the code cleaner and

Scan to Download
reducing verbosity.

3.Question
Can you explain what target-type inference is and how it
works in Java 8?
Answer:Target-type inference is the process where the Java
compiler determines the specific type of a generic argument
based on the expected type in a particular context. In Java 8,
this inference includes method arguments, meaning you can
call methods like 'cleanCars(Collections.emptyList())'
without needing to specify the type explicitly, which was
required in earlier versions.

4.Question
What are the practical benefits of using the enhanced type
inference in Java 8?
Answer:The practical benefits include increased code
readability and reduced boilerplate code. Developers no
longer need to redundantly specify types in many cases,
which streamlines the coding process and helps prevent
potential errors from manual inputs.

Scan to Download
5.Question
Can you provide an example of how to use the new
inference feature with a specific use case?
Answer:Certainly! Suppose you have a method 'cleanCars'
that cleans all cars in a list. With Java 8's enhancements, you
can easily filter a list of dirty cars and collect only the clean
ones like so:

List<Car> cleanCars = dirtyCars.stream()


.filter(Car::isClean)
.collect(Collectors.toList());

Here, 'Collectors.toList()' automatically infers that the list is


of type 'List<Car>', eliminating the need for additional type
specifications.
Chapter 26 | B.1 Collections| Q&A
1.Question
What is the significance of the new 'getOrDefault' method
in the Map interface introduced in Java 8?

Scan to Download
Answer:The 'getOrDefault' method simplifies the
process of handling absent keys in a Map by
allowing you to specify a default value to return
when the key is not found. This removes the need for
verbose idiomatic checks with 'containsKey' and
makes the code cleaner and easier to read. For
example, instead of writing multiple lines to check
and return a value, you can now do it in a single
line: Integer count = map.getOrDefault("Aston
Martin", 0); This enhances code efficiency and
streamlines operations.

2.Question
How does the 'computeIfAbsent' method improve caching
behavior in Java?
Answer:The 'computeIfAbsent' method optimizes the
caching pattern by condensing the logic into a single line of
code that both checks for the existence of a key in the cache
and populates it if absent. This is particularly useful when
fetching data from external sources. For instance, instead of

Scan to Download
writing several lines of code to first check if the data is
cached and then to fetch it if not, you can now simply use:
return cache.computeIfAbsent(url, this::getData); This not
only improves code readability but also reduces chances of
errors.

3.Question
What is the difference between the 'removeIf' method in
Collections and the 'filter' method in the Streams API?
Answer:The 'removeIf' method directly mutates the original
collection by removing elements that match a given
predicate, modifying the collection in place. In contrast, the
'filter' method in the Streams API creates a new stream
containing only the elements that match a predicate, leaving
the original collection unchanged. This distinction is crucial
for managing state in applications where the integrity of data
should be maintained.

4.Question
How does the 'replaceAll' method in the List interface
differ from the 'map' method in streams?

Scan to Download
Answer:The 'replaceAll' method mutates the existing
elements of a List by applying a specified operation, directly
changing the elements in place. In contrast, the 'map' method
in streams applies a transformation to each element and
produces a new stream with the transformed elements, thus
preserving the original data structure. For example:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.replaceAll(x -> x * 2); results in [2, 4, 6, 8, 10],
showing a direct modification. This emphasizes the differing
intent: mutation vs. transformation.

5.Question
What enhancements have been made to the Comparator
interface in Java 8?
Answer:Java 8 introduced several enhancements to the
Comparator interface, including default and static methods.
New methods like 'reversed' and 'thenComparing' allow for
more complex sorting strategies and chaining comparators
effectively. These additions offer developers a more powerful
and fluent way to define sorting logic, making it easier to

Scan to Download
compose multiple comparators. Additionally, methods like
'nullsFirst' and 'naturalOrder' cater to specific edge cases in
sorting, showcasing the versatility and robustness of the new
comparator functionalities.

6.Question
How do the updates to the Collections class affect how
collections are managed in Java 8?
Answer:The updates to the Collections class, which now
include methods to return unmodifiable, synchronized,
checked, and empty navigational collections, enhance the
way collections can be managed and interacted with. These
improvements not only promote better practices in terms of
thread safety and data integrity but also allow for cleaner API
usage when creating collections with specific constraints or
behaviors, which aligns with the modern programming
practices emphasized in Java 8.
Chapter 27 | B.2 Concurrency| Q&A
1.Question
What is one of the key advancements in Java 8 regarding
concurrency?

Scan to Download
Answer:The introduction of parallel streams, which
allows operations to be processed in parallel,
improving performance, especially for large
collections.

2.Question
What updates were made to the Atomic classes in Java 8?
Answer:New methods were introduced in the
java.util.concurrent.atomic package, including
getAndUpdate, updateAndGet, getAndAccumulate, and
accumulateAndGet, which enhance atomic operations on
numeric variables.

3.Question
When should LongAdder and LongAccumulator be used
over Atomic classes?
Answer:LongAdder and LongAccumulator should be used in
scenarios where multiple threads frequently update a variable
while reading infrequently, as they help reduce contention
and improve performance.

4.Question
How does ConcurrentHashMap improve performance

Scan to Download
compared to Hashtable?
Answer:ConcurrentHashMap allows concurrent reads and
updates by locking only portions of the map, leading to better
performance, especially when handling large amounts of
data.

5.Question
What efficient data structure does ConcurrentHashMap
use when bucket sizes exceed a threshold?
Answer:When bucket sizes become too large,
ConcurrentHashMap dynamically replaces them with sorted
trees, which offer O(log(n)) retrieval instead of O(n), thus
enhancing efficiency.

6.Question
How do the new stream-like operations in
ConcurrentHashMap work?
Answer:These operations, including forEach, reduce, and
search, operate concurrently and do not lock the map state,
enabling efficient processing of key-value pairs while
allowing functions applied to the entries to run

Scan to Download
independently.

7.Question
What is the significance of specifying a parallelism
threshold when using stream-like operations in
ConcurrentHashMap?
Answer:Specifying a parallelism threshold ensures that
operations execute sequentially if the current map size is too
small, helping to optimize resource usage by avoiding
unnecessary thread management for smaller datasets.

Scan to Download
Chapter 28 | B.3 Arrays| Q&A
1.Question
What is the significance of using the method
`reduceValues` in a `ConcurrentHashMap`?
Answer:The `reduceValues` method is significant
because it allows for parallel processing, where the
maximum value in a map can be computed
efficiently. By setting the threshold to 1, it utilizes
the common thread pool for maximal parallelism,
which can significantly speed up operations on large
datasets.

2.Question
Why should `mappingCount` be used instead of `size` in
`ConcurrentHashMap`?
Answer:`mappingCount` should be preferred over `size`
because it returns the count of mappings as a long,
accommodating larger data sizes that potentially exceed the
maximum limit of an int. This prevents potential overflow
issues when counting a vast number of entries in a concurrent

Scan to Download
map.

3.Question
What new functionalities does the `Arrays` class
introduce, and how do they enhance array manipulation?
Answer:The `Arrays` class introduces several new
functionalities including `parallelSort`, which allows for
efficient sorting in parallel, and `setAll` & `parallelSetAll`,
which enable setting all elements of an array through a
function, either sequentially or in parallel. These methods
leverage parallel processing to handle larger arrays more
efficiently and enhance performance.

4.Question
What is a practical example of using `Arrays.setAll`?
Answer:A practical example of using `Arrays.setAll` is to
create an array of even numbers. You can define an array of
size 10 and use `Arrays.setAll(evenNumbers, i -> i * 2)` to
fill it with values 0, 2, 4, 6, ..., which demonstrates how to
generate values dynamically based on their indices.

5.Question
How does the `keySet` method in `ConcurrentHashMap`

Scan to Download
improve data handling?
Answer:The `keySet` method enhances data handling by
providing a view of the map as a Set. This means that any
changes made to the map will automatically reflect in the Set,
and vice versa, facilitating easier manipulation of the keys
without having to maintain separate structures, which
enhances the usability and performance of collections.

6.Question
What important aspect of `parallelSetAll` must be
considered when using it, and why?
Answer:When using `parallelSetAll`, it is critical to ensure
that the function provided is side-effect free. This is
important because the operation runs concurrently across
multiple threads; side effects could lead to unpredictable
behavior and inconsistent results if multiple threads attempt
to modify shared state.
Chapter 29 | B.4 Number and Math| Q&A
1.Question
What is the purpose of the parallelPrefix method in Java?

Scan to Download
Answer:The parallelPrefix method is designed to
cumulatively apply a binary operator to the
elements of a given array in parallel, effectively
accumulating results across the entire array. This
allows for more efficient processing, especially with
large datasets, as it leverages multi-core processors.

2.Question
Can you give an example of how parallelPrefix is used?
Answer:Certainly! In the example provided, you start with an
array 'ones' filled with the value 1: int[] ones = new int[10];
Arrays.fill(ones, 1); Then, using parallelPrefix, each element
of the array is cumulatively summed:
Arrays.parallelPrefix(ones, (a, b) -> a + b); This results in the
array being transformed to [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], where
each position reflects the sum of all previous elements plus
the current one.

3.Question
What enhancements were made to the Number class in
Java 8?

Scan to Download
Answer:Java 8 enhanced the Number class by adding static
methods to the numeric wrappers like Short, Integer, Long,
Float, and Double, including methods for sum, min, and max.
Additionally, techniques for dealing with unsigned values
were introduced, and classes like Boolean and BigInteger
were given new static methods for logical operations and
precise conversions.

4.Question
How do the new methods in the Math class improve error
handling?
Answer:The Math class now includes methods such as
addExact, subtractExact, and multiplyExact, which throw an
arithmetic exception if an overflow occurs during operations.
This enhancement allows developers to handle errors more
effectively and prevents bugs related to unintended overflow.

5.Question
What implications do the unsigned methods in the Integer
and Long classes have for developers?
Answer:The addition of unsigned methods in the Integer and

Scan to Download
Long classes means that developers can work with unsigned
integers directly, which is crucial when dealing with binary
data or when high precision and non-negativity are required.
This allows for safer and more predictable arithmetic in
scenarios that involve comparing or manipulating large
ranges of integers.

6.Question
Why might the static method isFinite in the Double and
Float classes be important for developers?
Answer:The isFinite method is important because it allows
developers to check if a floating-point number is a finite
value, helping prevent potential errors due to infinite values
or NaN (Not a Number) scenarios, which can cause logical
errors in calculations and comparisons.

7.Question
What are the benefits of including logical operations in
the Boolean class?
Answer:Including logical operations like logicalAnd,
logicalOr, and logicalXor in the Boolean class streamlines

Scan to Download
the process of combining boolean values. This makes the
code cleaner and more expressive, removing the need for
developers to manually implement these logical operations
and improving overall code readability.

8.Question
How does the toIntExact method enhance data type
conversions?
Answer:The toIntExact method enhances type conversion by
providing a safe way to convert long values to ints. It checks
for overflow during conversion and throws an exception if
the long value exceeds the bounds of an int, thereby helping
to maintain data integrity and prevent errors that arise from
inappropriate type casting.

9.Question
What overall impact do the enhancements in Java 8 have
on programming efficiency?
Answer:The enhancements in Java 8, particularly those
related to the Number, Math, and Boolean classes,
significantly improve programming efficiency by providing

Scan to Download
developers with tools that minimize common errors, allow
efficient handling of large datasets, and offer clearer and
more functional approaches to arithmetic and logical
operations. This results in cleaner code, fewer bugs, and
more reliable applications.
Chapter 30 | B.7 String| Q&A
1.Question
What is the benefit of using the Files.lines method in
Java?
Answer:The Files.lines method allows for lazy
reading of a file as a stream, which means that the
file's content is read on-demand rather than all at
once. This is beneficial for handling large files
efficiently as it reduces memory consumption by
processing one line at a time.

2.Question
How does Files.walk differ from Files.list in the Java file
handling context?
Answer:Files.walk produces a recursive Stream<Path>,

Scan to Download
meaning it traverses all subdirectories and their contents,
while Files.list only provides a non-recursive listing of
entries in a specific directory. This makes Files.walk suitable
for situations where you need to access all files within a
directory tree.

3.Question
What new capabilities does the Reflection API provide in
Java 8?
Answer:The Reflection API has been enhanced to support the
changes in the annotation mechanism, allowing developers to
access method parameter information such as names and
modifiers through the new java.lang.reflect.Parameter class,
which improves introspection and enhances the ability to
work with method metadata.

4.Question
How does the String.join method simplify string
concatenation in Java?
Answer:The String.join method provides a simple and
convenient way to concatenate multiple strings with a

Scan to Download
specified delimiter. For example, String.join(", ", "Raoul",
"Mario", "Alan") efficiently constructs the single string
'Raoul, Mario, Alan', making code clearer and reducing the
likelihood of errors in manual concatenation.

5.Question
Can you explain the difference between lazy and eager
processing in the context of file streams in Java?
Answer:Lazy processing means that data is not loaded until it
is specifically requested, which conserves resources when
dealing with large datasets. In contrast, eager processing
loads all data upfront, potentially leading to higher memory
usage. The Files.lines method exemplifies lazy processing as
it reads lines from a file only as needed.

6.Question
How might using Files.find improve searching through
directories?
Answer:Files.find allows you to recursively search through
directories based on specified criteria (predicate), efficiently
locating files or folders that match specific attributes. This is

Scan to Download
particularly useful for managing and organizing large file
structures.

Scan to Download
Chapter 31 | C.1 Forking a stream| Q&A
1.Question
What is the purpose of the StreamForker class in Java
Streams?
Answer:The StreamForker class serves to perform
multiple operations in parallel on a single stream by
allowing users to fork the original stream into
several substreams, each associated with a specific
operation. It enables efficient parallel processing by
defining operations that can execute concurrently,
leveraging multi-core architectures.

2.Question
How does the fork method function in the StreamForker
class?
Answer:The fork method takes a key and a function to
transform the original stream into a result. It adds a
key-function pair to an internal map, allowing the user to
chain multiple forks, and returns the StreamForker instance
itself for a fluent API style.

Scan to Download
3.Question
Can you explain how results from each forked operation
are obtained?
Answer:Results from forked operations are obtained by
invoking the getResults method, which triggers the execution
of all the defined operations asynchronously. The results can
then be fetched using the get method of the Results interface,
requiring the corresponding key that was used during
forking.

4.Question
What is the role of the ForkingStreamConsumer class?
Answer:The ForkingStreamConsumer class implements the
Results and Consumer interfaces, handling the consumption
of elements from the original stream and distributing them to
multiple BlockingQueues. It also finalizes the processing by
signaling completion to each queue.

5.Question
Why is a BlockingQueue used in the StreamForker
framework?
Answer:A BlockingQueue is utilized to manage concurrent

Scan to Download
access and ensure thread safety while elements are being
processed by different operations. It allows multiple threads
to consume elements without conflict, preserving the order of
stream processing.

6.Question
How do Futures enhance the StreamForker's
performance?
Answer:Futures enhance performance by allowing operations
to be executed asynchronously. When a function is forked, a
CompletableFuture is used to manage the result of that
operation, which means the main thread can continue
executing without waiting for each operation to complete,
significantly improving overall responsiveness.

7.Question
What is an example of how to use the StreamForker with
a dataset?
Answer:An example usage involves processing a menu of
dishes to generate a short menu string, calculate total
calories, find the most caloric dish, and group dishes by type,

Scan to Download
all in parallel by forking the original stream and applying
specific operations simultaneously.

8.Question
How does one ensure that the operations in the
StreamForker are executed in order?
Answer:To ensure operations are executed in a controlled
manner, the operations are defined to be sequentially
processed through the ForkingStreamConsumer without
parallelization, which avoids potential out-of-order execution
issues.

9.Question
What will happen if a key used in the fork method is not
present when retrieving results?
Answer:If a key used in the fork method is not present when
retrieving results, the get method will likely return null or
throw an error, depending on the implementation of the
Results interface, indicating that the requested operation has
not been defined.
Chapter 32 | D.1 Anonymous classes| Q&A

Scan to Download
1.Question
Why are lambda expressions preferred over anonymous
classes in Java?
Answer:Lambda expressions are preferred because
they do not generate a new class file for each
instance, which improves the application’s startup
performance. Utilizing lambda expressions avoids
the performance drawbacks associated with the
creation of multiple anonymous classes.

2.Question
What are the performance issues related to anonymous
classes mentioned in the text?
Answer:The performance issues with anonymous classes
include: 1) Each anonymous class generates a new class file
that impacts startup time, as all class files need to be loaded
and verified. 2) The introduction of many subtypes for
classes or interfaces complicates the class hierarchy and can
lead to inefficient memory usage.

3.Question
How does the Java compiler handle lambda expressions

Scan to Download
differently compared to anonymous classes?
Answer:Instead of translating lambda expressions into
anonymous classes, the Java compiler utilizes a mechanism
that allows lambda expressions to retain a simpler form,
thereby reducing the overhead associated with class file
generation and improving runtime performance.

4.Question
Can you give an example of a situation where using
lambda expressions significantly improves performance
over anonymous classes?
Answer:For instance, if you need to define multiple
comparators for sorting a large dataset, using lambda
expressions allows you to define these comparators inline
without generating separate class files for each one. This
would drastically reduce memory overhead and enhance
startup performance, making the application faster.

5.Question
What might happen if Java relied solely on anonymous
classes for lambda expressions?

Scan to Download
Answer:If Java relied solely on anonymous classes, it would
lead to a proliferation of class files for each lambda
expression, severely hindering performance due to increased
loading times and potentially exhausting system resources
through too many class definitions. This could lead to slower
applications and a less efficient development process.
Chapter 33 | D.2 Bytecode generation| Q&A
1.Question
What does bytecode generation imply for the
performance of Java applications?
Answer:Bytecode generation can lead to the creation
of numerous subtypes of Comparator, which may
complicate the JVM's ability to optimize runtime
performance efficiently. This overhead could slow
down the execution of Java applications,
particularly when these subtypes are numerous.

2.Question
How does the Java compiler convert source code into
executable format?

Scan to Download
Answer:The Java source code is compiled into Java bytecode
via the Java compiler. This bytecode is then executed by the
Java Virtual Machine (JVM), enabling the application to run.
This process is crucial for allowing platform independence in
Java.

3.Question
What is the significance of using anonymous inner classes
in Java, particularly in the context of the Function
interface?
Answer:Anonymous inner classes provide a way to
instantiate and implement interfaces like Function without
needing a separate named class. They allow for clear and
concise code, although they may produce more complex
bytecode, which can impact performance.

4.Question
How can you inspect the bytecode of a Java class file?
Answer:You can inspect the bytecode and constant pool of
any Java class file using the command `javap -c -v
ClassName`. This command provides detailed information

Scan to Download
about the bytecode instructions that were generated by the
compiler.

5.Question
What is an example of bytecode generated from an
anonymous inner class?
Answer:The bytecode generated from implementing the
Function interface as an anonymous inner class includes
operations like 'aload_0' to load the object onto the stack,
'new' to create a new instance of the anonymous class, 'dup'
to duplicate the reference on the stack, and 'invokespecial' to
call the constructor of that class.

6.Question
What are the key operations involved when creating a
new instance of an anonymous inner class in Java?
Answer:The key operations include loading the current
object onto the stack (aload_0), creating a new instance of
the class (new), duplicating the reference (dup), and
initializing the object using its constructor (invokespecial).
Finally, the instance is stored in a field of the enclosing class.

Scan to Download
7.Question
What implications does the Java bytecode generation
have for developers looking to improve performance?
Answer:Developers should be aware that excessive bytecode
generation from constructs like anonymous inner classes can
hinder optimizations by the JVM, suggesting that for
performance-critical applications, alternatives like lambda
expressions or named classes may be preferable.

8.Question
Can you explain the process of using the Function
interface in a practical example?
Answer:In the provided example, an instance of the Function
interface is created using an anonymous inner class, which
implements the apply method to convert an object to its
string representation. This demonstrates a functional
programming style in Java, which can encapsulate behavior
and enhance code readability.

Scan to Download
Chapter 34 | D.3 Invokedynamic to the rescue| Q&A
1.Question
What is the significance of lambda expressions in Java 8
regarding memory efficiency compared to anonymous
inner classes?
Answer:Lambda expressions in Java 8 offer
significant memory efficiency improvements over
anonymous inner classes. Instead of creating a new
class file for each lambda, the bytecode utilizes the
'invokedynamic' instruction, which reduces the
overhead of class loading and instantiation. This
allows for greater flexibility and lower memory
consumption, making the execution of functions
more lightweight.

2.Question
Can you explain the role of the 'invokedynamic'
instruction in Java?
Answer:The 'invokedynamic' instruction plays a crucial role
in the Java Virtual Machine by allowing for dynamic method
invocation. It adds a layer that enables the JVM to determine

Scan to Download
the call target at runtime, accommodating dynamically typed
languages. This is particularly useful for scenarios where
method signatures aren't known at compile time, thus
enhancing versatility in functional programming within Java.

3.Question
How does the code representation of lambda expressions
differ from that of anonymous inner classes?
Answer:In the case of anonymous inner classes, each lambda
results in a separate class file (e.g., InnerClass$1), leading to
additional memory overhead. However, with lambda
expressions, the bytecode leverages 'invokedynamic',
resulting in more compact code with fewer class
instantiations. This difference illustrates Java's evolution
towards a more functional style while optimizing for
resources.

4.Question
What implications does the introduction of lambda
expressions and 'invokedynamic' have for Java
developers?
Answer:The introduction of lambda expressions and

Scan to Download
'invokedynamic' allows developers to write cleaner, more
concise code while maintaining high performance and
leveraging functional programming paradigms. It simplifies
coding patterns, encourages immutability, and enhances
readability, thus allowing developers to focus on business
logic rather than boilerplate code.

5.Question
How did the changes introduced in Java 8 impact the way
Java is perceived in comparison to other programming
languages?
Answer:With the introduction of lambda expressions and
functional programming features in Java 8, Java is now better
positioned to compete with other languages that have long
embraced these paradigms, such as Scala and Kotlin. This
shift allows Java to be more versatile and modern, appealing
to a broader range of developers, especially those coming
from languages that prioritize functional programming.
Chapter 35 | D.4 Code-generation strategies| Q&A
1.Question
What are the benefits of using invokedynamic for lambda

Scan to Download
expressions in Java?
Answer:Using invokedynamic for lambda
expressions allows for delaying the bytecode
translation until runtime, which introduces several
benefits: it keeps the translation strategy as an
implementation detail, prevents overhead when
lambdas are unused, supports caching instances of
stateless lambdas, avoids additional performance
costs by linking the implementation only at the first
invocation.

2.Question
How does the translation of a stateless lambda expression
work?
Answer:The translation of a stateless lambda expression
involves generating a static method at runtime with the same
signature as the lambda. This method, such as 'static String
lambda$1(Object obj)', serves to define the behavior of the
lambda without needing to manage any state.

3.Question

Scan to Download
What complicates the translation process of a capturing
lambda expression?
Answer:For capturing lambda expressions, the translation
becomes complex because the lambda captures final or
effectively final local variables. The generated method must
include additional arguments for these captured variables,
altering its signature to accommodate the context.

4.Question
What is the role of the bootstrap method in lambda
translation?
Answer:The bootstrap method is crucial in defining which
method implementation to invoke for the lambda expression.
It consults the language-dependent logic and returns a 'linked
call site' that ensures subsequent calls do not need to
rediscover the method.

5.Question
Why is it advantageous to cache instances of stateless
lambdas?
Answer:Caching instances of stateless lambdas is

Scan to Download
advantageous because it reduces the need to create new
objects for each invocation, thereby improving performance
and memory usage, especially in cases where the same
lambda is called multiple times.

6.Question
How does the JVM ensure backward compatibility with
lambda expressions?
Answer:By deferring the implementation strategy for
translating lambda expressions to runtime, the JVM can
change or optimize these strategies in future versions without
breaking existing bytecode, ensuring backward compatibility.

7.Question
What is an example of how a capturing lambda modifies
its generated method signature?
Answer:A capturing lambda modifies its generated method
signature by adding extra parameters for each captured
variable. For instance, if a lambda captures a 'header'
variable, the signature might change from 'static String
lambda$1(Object obj)' to 'static String lambda$1(String

Scan to Download
header, Object obj)'.

8.Question
What implications does the choice of invokedynamic have
for developers?
Answer:The use of invokedynamic gives developers
flexibility in how lambda expressions are implemented,
allowing for future optimizations without breaking existing
code, and enables developers to write cleaner and more
efficient code by focusing on functional programming
practices.
Chapter 36 | A| Q&A
1.Question
What are the key principles of asynchronous
programming as outlined in Chapter 36?
Answer:Asynchronous programming allows
non-blocking code execution, enabling programs to
handle multiple tasks simultaneously. Key principles
include using CompletableFutures, implementing
asynchronous APIs, converting synchronous

Scan to Download
methods to asynchronous ones, and pipelining
asynchronous tasks.

2.Question
How do CompletableFutures enhance the handling of
asynchronous tasks?
Answer:CompletableFutures provide a powerful way to
compose and combine multiple asynchronous tasks, allowing
developers to react to task completion, handle potential
errors, and utilize methods to combine results from different
futures seamlessly.

3.Question
What are some common pitfalls when implementing
asynchronous APIs?
Answer:Common pitfalls include mismanagement of errors,
overlooking race conditions, creating blocking code within
async tasks, and failing to apply appropriate timeouts, which
can lead to performance degradation and unresponsive
applications.

4.Question
Can you explain the method 'allOf' in the context of

Scan to Download
CompletableFutures?
Answer:The 'allOf' method allows you to handle a collection
of CompletableFutures, meaning that you can wait for all the
futures to complete. It creates a new CompletableFuture that
completes when all provided futures complete, which is
useful for executing multiple asynchronous operations in
parallel and aggregating their results.

5.Question
What is an example of converting a synchronous method
to an asynchronous one?
Answer:An example is taking a traditional method that
fetches data like 'getData()' and wrapping it in a
CompletableFuture, allowing the method to return
immediately and run the data fetching in the background,
thus improving responsiveness.

6.Question
How does the implement 'reacting to CompletableFuture
completion' enhance user experience?
Answer:Reacting to CompletableFuture completion, you can

Scan to Download
trigger UI updates or execute follow-up tasks immediately
after a long-running operation finishes, improving user
experience by providing instant feedback and minimizing
waiting times.

7.Question
What is the significance of using annotations in Java
programming as mentioned in the chapter?
Answer:Annotations add meta-information to code,
facilitating the implementation of frameworks, improving
readability, and enabling specific functionalities like
validation or data-binding without boilerplate coding.

8.Question
Describe how 'pipelining asynchronous tasks' works and
its benefits.
Answer:Pipelining allows you to chain multiple
asynchronous operations together so that the output of one
operation can be fed directly into the next. This enhances
efficiency by reducing the overhead of managing multiple
threads and optimizing resource usage, making code cleaner

Scan to Download
and improving execution time.

Scan to Download
Chapter 37 | C| Q&A
1.Question
What is the significance of using lambda expressions in
Java?
Answer:Lambda expressions simplify the
implementation of functional interfaces, allowing for
more concise and readable code. By enabling
behavior parameterization, they facilitate cleaner
operations such as filtering and sorting, thus
reducing boilerplate code.

2.Question
How does behavior-driven development (BDD) influence
software design?
Answer:BDD focuses on collaboration between developers,
QA, and non-technical stakeholders, which fosters shared
understanding of requirements. This leads to more
user-centric functionalities and tests that align closely with
business outcomes.

3.Question
Why is it important to consider the concept of

Scan to Download
backpressure in reactive programming?
Answer:Backpressure is crucial as it helps manage the flow
of data between producers and consumers in a system to
prevent overload. It ensures that a system remains responsive
and efficient, even under high load, by allowing consumers
to signal to producers to slow down.

4.Question
What role does the CompletableFuture API play in
asynchronous programming?
Answer:CompletableFuture provides a powerful framework
for writing non-blocking asynchronous code. It allows
developers to compose and chain multiple asynchronous
tasks, handle errors, and react to the completion of
operations, leading to cleaner and more maintainable code in
concurrent applications.

5.Question
Can you explain the concept of a combiner in Java's
collector framework?
Answer:A combiner is a method invoked when collecting in

Scan to Download
parallel. It combines results from different threads into a
single result. This is particularly useful for performance
optimization in operations like summing or grouping large
streams of data, ensuring that the results of parallelized tasks
can be efficiently aggregated.

6.Question
How does the Executors framework improve concurrency
in Java applications?
Answer:The Executors framework abstracts thread
management, allowing developers to manage a pool of
threads without directly overseeing their lifecycle. This
simplifies concurrent programming by providing high-level
utilities for task execution and resource management, leading
to more efficient and scalable applications.

7.Question
What benefits do enhanced Collection API features bring
to Java developers?
Answer:Enhanced Collection API features allow for more
versatile data structures and operations, such as immutable

Scan to Download
collections and new factory methods. These improvements
lead to reduced boilerplate code, increased safety, and better
performance through optimized data handling.

8.Question
Why is understanding atomic operations important for
developing concurrent applications?
Answer:Atomic operations guarantee that a sequence of
actions is completed without interruption, which is vital in
multi-threaded environments to avoid race conditions.
Understanding these operations allows developers to write
safer and more reliable concurrent code.

9.Question
Explain the purpose of the 'blockingSubscribe' method in
the context of reactive programming.
Answer:The 'blockingSubscribe' method allows a subscriber
to block until all emitted items are consumed. This is useful
for scenarios where you want to ensure that processing
completes before continuing execution, helping to
synchronize reactive streams with imperative code.

Scan to Download
10.Question
What insights does the behavior parameterization
provide in designing user interfaces?
Answer:Behavior parameterization allows developers to
define varying behaviors dynamically based on user
interactions. This makes user interfaces more adaptable and
enables personalized experiences which can directly improve
user satisfaction and engagement.
Chapter 38 | D| Q&A
1.Question
What is the significance of the ConcurrentHashMap class
in Java, and how does it enhance performance in
concurrent programming?
Answer:The ConcurrentHashMap class is essential
in Java for managing concurrent access to a hash
table. It allows multiple threads to read and write
data simultaneously without locking the entire map,
which greatly improves performance and scalability
in multi-threaded applications. Features like
segmented locking and its concurrent methods help

Scan to Download
prevent ConcurrentModificationExceptions, making
it ideal for high-performance data processing. By
supporting efficient 'reduce' and 'search' operations,
it allows developers to build robust applications that
can handle large volumes of concurrent tasks.

2.Question
How can the concept of 'decoupling in time' benefit
software architecture and the maintenance of Java
applications?
Answer:Decoupling in time refers to the ability to separate
components so that they do not depend on each other's
timing, allowing for greater flexibility in software
architecture. This principle benefits Java applications by
enabling developers to change, replace, or update parts of the
system without impacting the entire application. It supports
adding new features or fixing bugs without downtime, thus
enhancing the maintainability and adaptability of software
systems.

3.Question
Why is the don't repeat yourself (DRY) principle

Scan to Download
important in software development, particularly in Java?
Answer:The DRY principle is crucial in software
development because it promotes code reuse and avoids
redundancy. In Java, applying the DRY principle leads to
cleaner, more manageable codebases by ensuring that each
piece of knowledge is represented in a single place. This
reduces the chances of errors during updates and simplifies
the debugging process, as changes only need to be made in
one location. Ultimately, adhering to DRY results in faster
development cycles and higher quality code.

4.Question
Explain the role of the Cucumber framework in the
context of domain-specific languages (DSLs) in Java and
their impact on testing. How can this improve
collaboration between team members?
Answer:Cucumber is a significant tool that supports the
creation of DSLs, specifically geared towards
behavior-driven development (BDD). It allows developers to
write tests in a natural language format that is easily

Scan to Download
understandable by non-technical stakeholders. By facilitating
collaboration between developers, testers, and business
analysts, Cucumber helps ensure that all parties have a clear
understanding of the requirements. This leads to more
meaningful tests that genuinely reflect user expectations,
enhancing the overall quality of the software.

5.Question
How does the Stream interface and its operations in Java
promote functional programming principles?
Answer:The Stream interface in Java enables developers to
work with sequences of data in a fluent, declarative manner,
which is a key aspect of functional programming. By
utilizing operations such as map, filter, and reduce,
programmers can express complex data transformations in a
concise and readable way. This shifts focus from imperative
logic to a more functional style, where side effects are
minimized and functions are treated as first-class citizens,
ultimately leading to cleaner and more maintainable code.

6.Question

Scan to Download
What are the advantages of using Optional methods in
Java, specifically in terms of improving code safety and
expressiveness?
Answer:Optional methods in Java provide a way to handle
the presence or absence of values without the risk of
NullPointerExceptions. This enhances code safety by
encouraging developers to explicitly check for the presence
of a value, leading to clearer and more expressive code. By
using Optional, code becomes self-documenting, conveying
the intention and handling of potentially missing values more
effectively, making it easier to understand and maintain.

7.Question
Discuss the implications of having default methods in
interfaces in Java in the context of evolving APIs. How do
they help in maintaining backward compatibility?
Answer:Default methods in interfaces allow developers to
add new methods without breaking existing implementations.
This means that when evolving APIs, developers can
introduce new functionality while maintaining backward

Scan to Download
compatibility with older versions of the interface. This
flexibility encourages the evolution of libraries and
frameworks in Java without forcing all implementers to
immediately adapt their code. As a result, it fosters a
smoother transition for developers and enhances the
longevity of codebases.
Chapter 39 | F| Q&A
1.Question
What are DSLs and how do they enhance Java
programming?
Answer:Domain-Specific Languages (DSLs) are
tailored programming languages designed to solve
specific problems within a particular domain
effectively. In Java, DSLs can be categorized into
external and internal varieties, with the former
operating independently and the latter integrated
into the host language. The introduction of DSLs can
significantly increase code expressiveness and
efficiency, as they allow developers to write solutions

Scan to Download
that closely resemble the problem domain's
requirements.

2.Question
Can you explain the difference between external and
internal DSLs in Java?
Answer:External DSLs are stand-alone languages, often with
their own parsers and compilers, designed for specific tasks,
while internal DSLs leverage the existing syntax and
semantics of Java. For instance, an external DSL might be a
custom scripting language for database queries, whereas an
internal DSL might be fluent APIs created within Java to
provide a more descriptive interface.

3.Question
What is the purpose of the 'forEach' method in Java, and
how does it improve code readability?
Answer:The 'forEach' method is a critical function of the
Java Stream API that allows developers to iterate over a
collection with a lambda expression or method reference.
This enhances readability by eliminating boilerplate code

Scan to Download
associated with traditional loops, enabling more declarative
and expressive programming styles. For example, instead of
writing multiple lines to filter and process a list, a single line
using 'forEach' can succinctly describe the intent.

4.Question
What role does the 'Fork/Join' framework play in Java,
and why is it important for performance?
Answer:The Fork/Join framework in Java facilitates parallel
programming by allowing tasks to be divided into smaller
subtasks, which can be executed concurrently. This is crucial
for performance optimization, as it takes advantage of
multi-core processors to improve efficiency in handling
large-scale computational tasks. It utilizes work-stealing
algorithms, meaning idle threads can 'steal' tasks from busy
ones, balancing the workload for better resource
management.

5.Question
How does using method references in Java enhance code
efficiency?

Scan to Download
Answer:Method references simplify the syntax used in Java
by allowing developers to refer directly to methods without
executing them, acting as a shorthand for lambda
expressions. This leads to cleaner and more readable code,
particularly when performing operations such as filtering or
transforming collections, ultimately enhancing
maintainability without sacrificing performance.

6.Question
What are first-class functions and why are they
significant in Java?
Answer:First-class functions refer to the treatment of
functions as first-class citizens; they can be passed as
arguments, returned from other functions, and assigned to
variables. In Java, this concept enhances functional
programming capabilities, encouraging a programming style
that favors immutability and higher-order functions. The
significance lies in their ability to create more flexible and
reusable code—especially with the advent of Lambda
expressions and functional interfaces.

Scan to Download
7.Question
Can you give an example of how the 'filter' method
operates in a Stream?
Answer:The 'filter' method in Java Streams allows for the
exclusion of elements from a stream based on specific
criteria defined by a predicate. For example, if you have a list
of integers and want to create a stream of only even numbers,
you could use the filter method like this:
'numbers.stream().filter(n -> n % 2 ==
0).collect(Collectors.toList());'. This line succinctly
communicates the operation of extracting even values,
enhancing code clarity.

8.Question
What does encapsulation mean in the context of Java, and
why is it essential?
Answer:Encapsulation in Java is the practice of bundling the
data (attributes) and methods (behavior) that operate on the
data into a single unit or class, restricting access to the
internal state by making it private. This is essential for

Scan to Download
protecting the integrity of the data, promoting modularity,
and allowing for controlled access through public methods
(getters and setters). For instance, keeping sensitive
information private encourages a design that minimizes the
risk of unintended interference from external code.

9.Question
What does the term 'empty Optionals' imply, and how
does it improve handling null values?
Answer:An 'empty Optional' in Java is a container object
which may or may not contain a non-null value. It serves as a
powerful alternative to null references, helping to avoid
NullPointerExceptions and promoting clearer code that
explicitly handles the presence or absence of values. For
example, instead of returning null, a method can return
Optional.empty(), leading to a more predictable and safer
coding practice.

Scan to Download
Chapter 40 | I| Q&A
1.Question
What is the significance of functional interfaces in Java?
Answer:Functional interfaces are essential because
they allow for the use of lambda expressions and
method references, enabling a functional
programming style. They represent a single abstract
method, which can be implemented in a concise
manner, thus promoting cleaner and more readable
code.

2.Question
Can you explain the concept of currying in functional
programming?
Answer:Currying is a technique where a function with
multiple arguments is transformed into a sequence of nested
functions, each taking a single argument. For example,
instead of a function f(x, y), you would have a function
f(x)(y). This allows partial application of functions and
greater flexibility in how functions are combined.

Scan to Download
3.Question
How do lazy evaluation and streams enhance
performance in Java?
Answer:Lazy evaluation means that expressions are not
evaluated until their values are needed, which can lead to
improved performance. In Java, streams utilize this concept,
allowing for efficient data processing as operations on
streams are only executed when necessary, reducing
unnecessary computations and enhancing resource
utilization.

4.Question
What are higher-order functions and why are they
important?
Answer:Higher-order functions are functions that can take
other functions as arguments or return them as results. They
are important because they enable functional programming
constructs like map, filter, and reduce, allowing for more
abstract and flexible handling of operations on collections.

5.Question
Could you provide an example of how persistence is

Scan to Download
handled in functional programming?
Answer:In functional programming, persistent data structures
allow for immutability and safe sharing of data. For instance,
instead of modifying a list directly, you create a new version
of that list with the changes reflected, while keeping the
original intact. This approach prevents side effects and
enhances the reliability of programs.

6.Question
What is 'referential transparency' and why is it a crucial
concept in functional programming?
Answer:Referential transparency means that an expression
can be replaced with its value without changing the
program's behavior. This property is crucial because it
enables reasoning about code more easily, allows for
optimizations by the compiler, and fosters a clearer
understanding of how functions interact.

7.Question
What role do decorators play in functional programming
with respect to function composition?

Scan to Download
Answer:Decorators in functional programming allow you to
wrap or modify function behavior without changing the
function's internal logic. They facilitate function
composition, where functions are combined to build more
complex operations while maintaining modular code.

8.Question
How does Java's approach to functional programming
compare with more traditional object-oriented
programming?
Answer:Java's approach to functional programming
emphasizes immutability and first-class functions,
contrasting with traditional object-oriented programming that
relies on mutable state and behavior encapsulated within
objects. This shift enables more declarative code that focuses
on 'what' should be done rather than 'how' to do it.

9.Question
What is the 'execute-around pattern' and where is it
typically applied?
Answer:The execute-around pattern is a design pattern that
provides a template for managing resources. It is often used

Scan to Download
in scenarios where you need to ensure proper opening and
closing of resources, like files or database connections,
ensuring they are available for the duration of their usage and
properly disposed of afterward.

10.Question
How does functional programming in Java help in
writing concurrent and parallel applications?
Answer:Functional programming concepts, such as
immutability and stateless functions, make it easier to write
concurrent and parallel applications because they avoid side
effects and shared mutable data that can lead to race
conditions. This results in safer, more predictable, and
easier-to-manage parallel computations.
Chapter 41 | J| Q&A
1.Question
What is the significance of infinite streams in Java?
Answer:Infinite streams allow developers to create
stream pipelines that can generate potentially
unbounded sequences of data. This opens up

Scan to Download
possibilities for processing data on-the-fly without
the need to pre-load or limit datasets, enhancing
performance and scalability in applications.

2.Question
How do interfaces enhance programming in Java?
Answer:Interfaces enable a level of abstraction that allows
for behavior-based programming. By defining contracts
without dictating how they are implemented, interfaces
encourage flexibility and the ability to develop polymorphic
behavior, facilitating easier testing and maintenance.

3.Question
What is the impact of the Java module system introduced
in JDK 9?
Answer:The Java module system provides a way to organize
and encapsulate code. It facilitates better separation of
concerns, enhances maintainability, and improves security by
allowing developers to specify the visibility of packages and
classes, thus minimizing dependencies.

4.Question
Can you explain the significance of default methods in

Scan to Download
interfaces?
Answer:Default methods in interfaces allow developers to
add new methods to interfaces without breaking existing
implementations. This is particularly useful for evolving
APIs while maintaining backward compatibility, making it
easier to enhance functionality without imposing additional
burden on implementing classes.

5.Question
What role do intermediate operations play in stream
processing?
Answer:Intermediate operations are operations on a stream
that transform data and return another stream. They are lazily
evaluated, meaning computations are not performed until a
terminal operation is invoked. This allows for optimization in
pipelined processing of large datasets, as operations can be
stacked and executed in a single pass.

6.Question
How does behavior parameterization contribute to
flexible code design?

Scan to Download
Answer:Behavior parameterization allows developers to
define methods that accept behavior as parameters, typically
using functional interfaces or lambda expressions. This
approach enables more generic and reusable code, fostering a
design that can adapt its behavior without altering the
underlying implementation.

7.Question
What is the importance of the IntStream and its methods
in Java?
Answer:The IntStream class provides a specialized stream
for handling primitive int values efficiently. Its methods like
IntStream.iterate and IntStream.concat simplify working with
sequences of integers, supporting functional-style operations
without the overhead of boxing/unboxing, thus improving
performance.

8.Question
How do internal domain-specific languages (DSLs)
enhance code expressiveness?
Answer:Internal DSLs provide a way to create APIs that

Scan to Download
resemble a domain language, making the code more
expressive and easier to understand. By utilizing Java’s
syntax, they enable developers to tailor APIs specifically for
certain tasks or domains, enhancing readability and focusing
on the business problem at hand.

9.Question
What are the benefits of using Java's processing streams?
Answer:Processing streams allow for functional-style
operations on collections of data, making it easier to perform
parallel operations and aggregate results. This leads to
cleaner code, reduced boilerplate, and improved performance
through optimized data handling, especially in data-intensive
applications.

10.Question
Why is effective error handling, like IOException, crucial
in Java applications?
Answer:Effective error handling is vital in Java applications
to maintain robustness and provide meaningful feedback
during exceptions. IOExceptions can arise from various

Scan to Download
input/output operations, and handling them properly ensures
that applications can respond gracefully to failures and
continue functioning or provide relevant error messages to
users.

11.Question
How does the Java Enhancement Proposal (JEP) process
influence Java's evolution?
Answer:The JEP process serves as a structured mechanism
for proposing and discussing changes to the Java platform. It
encourages community involvement and ensures that
enhancements are reviewed and considered thoughtfully,
thereby guiding the language's evolution in a way that meets
developers' needs and advances technology.
Chapter 42 | L| Q&A
1.Question
How has the introduction of functional programming
concepts like lambda expressions changed the way we
write Java code?
Answer:Lambda expressions enable a concise and
expressive way to write code, allowing functions to

Scan to Download
be treated as first-class citizens. This shift helps in
creating cleaner, more readable code and encourages
the use of functional interfaces which can simplify
tasks such as filtering and collecting data from lists.

2.Question
What role do functional interfaces play in Java
programming, especially with respect to lambda
expressions?
Answer:Functional interfaces are crucial in Java as they
provide a target type for lambda expressions. A functional
interface contains a single abstract method that can be
implemented using a lambda, which streamlines code by
reducing boilerplate while still adhering to the principles of
object-oriented programming.

3.Question
Can you explain the concept of higher-order functions in
the context of Java and give an example?
Answer:Higher-order functions are functions that can take
other functions as arguments or return them as results. In
Java, you can create higher-order functions using functional

Scan to Download
interfaces. For example, you can create a method that takes a
Function<Object, String> as a parameter to convert objects
into strings in various ways, resulting in more reusable and
flexible code.

4.Question
What is the importance of laziness in Java streams, and
how does it impact performance?
Answer:Laziness in Java streams allows for the deferred
execution of computations. This means that operations are
not performed until they are explicitly needed, which can
lead to performance improvements by avoiding unnecessary
calculations and allowing operations to be fused together. For
instance, when filtering and mapping a collection, lazy
evaluation ensures that each element is processed only once.

5.Question
How can design patterns be integrated with the functional
programming approach in Java?
Answer:Design patterns, such as the strategy or observer
pattern, can be enhanced by incorporating functional

Scan to Download
programming concepts. By using lambda expressions or
method references, we can provide behavior to these patterns
in a more succinct way, making the implementation more
flexible and easier to understand.

6.Question
What challenges does Java face with type checking in
lambda expressions and how can they be addressed?
Answer:While Java's static type system works well to catch
errors at compile-time, lambda expressions can lead to
potential ambiguity in type inference. This can be managed
by providing explicit types for parameters where necessary or
using functional interfaces intended for specific operations to
guide the compiler.

7.Question
How does local variable type inference simplify the use of
lambdas in Java?
Answer:Local variable type inference allows programmers to
declare local variables without specifying the type explicitly,
simplifying code readability, especially within lambda

Scan to Download
expressions. For instance, instead of declaring 'List<String>
list = new ArrayList<>();', one can use 'var list = new
ArrayList<>();', making it easy to use with lambdas without
verbose type declarations.

8.Question
Explain how the concept of lazy evaluation can be applied
to create infinite data structures in Java. Provide an
example.
Answer:Lazy evaluation can be used to define streams that
generate elements on demand, allowing for the creation of
infinite sequences. For example, you can create a stream that
generates Fibonacci numbers, producing each number only
when requested, using a recursive lambda function.

9.Question
What benefits do functional programming concepts bring
to Java's concurrency model?
Answer:Functional programming offers immutability and
statelessness, which are essential in concurrent programming.
By using immutable data structures and pure functions, we
can eliminate side effects, making it far easier to write safe

Scan to Download
concurrent code without the need for extensive locking
mechanisms.

10.Question
Discuss the connection between Mathematics and the use
of lambdas in Java. How can this understanding improve
programming practices?
Answer:Mathematics provides a theoretical foundation for
functional programming through concepts such as lambda
calculus, which parallels the use of lambdas in Java.
Understanding these concepts can deepen a programmer's
insight into functional patterns, leading to more efficient
algorithms and clearer code structures that can improve
collaboration and maintenance.

Scan to Download
Chapter 43 | N| Q&A
1.Question
What is method chaining in Java, and why is it
beneficial?
Answer:Method chaining is a programming style
that allows multiple method calls to be chained
together in a single statement. This is achieved by
having each method return the object itself (usually
'this') after performing its operation. Method
chaining enhances code readability and conciseness,
making it easier to follow the flow of logic in the
code. For example, instead of calling multiple setters
on an object like this:

```java
object.setA(valueA);
object.setB(valueB);
object.setC(valueC);
```

Scan to Download
You could use method chaining:

```java
object.setA(valueA).setB(valueB).setC(valueC);
```

This approach leads to a more fluent programming


style, allowing for cleaner and more expressive code.

2.Question
How does the new module system in Java affect
application design?
Answer:The new module system introduced in Java 9
enhances application design by allowing developers to
explicitly define module boundaries and dependencies. With
the introduction of the 'module-info.java' file, developers can
declare which packages are accessible to other modules and
which packages are encapsulated, improving encapsulation
and reducing the risk of unintended interactions between

Scan to Download
components. This modular approach encourages better
organization of code, improves maintainability, and enables
better scaling of applications as they grow. Moreover, it
supports long-term support (LTS) of specific modules,
ensuring stability in production systems.

3.Question
What is memoization, and how can it improve
performance in Java applications?
Answer:Memoization is an optimization technique used to
improve the performance of functions by caching their
results. When a function is called with a specific set of
parameters, the result is stored so that subsequent calls with
the same parameters can be retrieved from the cache instead
of recomputing it. This can significantly enhance the
performance of programs, especially in computationally
intensive tasks or recursive functions. For instance, a
recursive function that calculates Fibonacci numbers can be
improved with memoization by storing previously computed
results, thus avoiding exponential time complexity and

Scan to Download
transforming it into a linear time algorithm.

4.Question
What challenges does multithreading introduce in Java,
and how can they be mitigated?
Answer:Multithreading introduces several challenges, such
as race conditions, deadlocks, and difficulties in debugging.
Race conditions occur when multiple threads attempt to read
and write shared data concurrently, leading to unpredictable
behavior. To mitigate this, synchronization mechanisms such
as 'synchronized' blocks or 'Locks' can be employed to ensure
that only one thread accesses the shared resource at any given
time. Deadlocks can occur when two or more threads are
waiting indefinitely for resources held by each other. This
can be avoided by following a strict order of resource
acquisition. Additionally, using higher-level abstractions
provided by the Java concurrency API, such as
'ExecutorService' or 'CountDownLatch,' can simplify the
handling of threading complexities.

5.Question

Scan to Download
What are the advantages of using streams in Java 8 and
beyond?
Answer:Streams in Java 8 introduced a powerful abstraction
for processing sequences of elements, providing several key
advantages. Firstly, they promote a functional programming
style by allowing operations like map, filter, and reduce,
which can lead to more declarative code that expresses 'what'
you want to achieve, rather than 'how' to achieve it. Streams
also leverage lazy evaluation, meaning that intermediate
operations are not computed until a terminal operation is
invoked, which can improve performance by avoiding
unnecessary processing. Additionally, streams can easily take
advantage of multicore architectures for parallel processing,
enabling more efficient data handling without complex
thread management. For example, using 'parallelStream()' on
a collection allows for automatic parallelization with
minimal effort.
Chapter 44 | P| Q&A
1.Question

Scan to Download
What are the alternatives to null values that are discussed
in this chapter, especially in relation to Optionals?
Answer:The chapter discusses Optionals as a
primary alternative to null values, addressing issues
associated with null references. Specifically, it
explains how to wrap potentially null values in
Optionals, highlighting methods like
Optional.ofNullable, which allows for safe handling
of nulls by encapsulating values. Other alternatives
mentioned include various defensive programming
techniques aimed at reducing NullPointerExceptions
and comparing Java's approach to handling absence
of values with that of other programming languages.

2.Question
How can Optionals reduce the occurrence of
NullPointerExceptions?
Answer:Optionals provide a structured way to handle the
absence of a value without resorting to null references, which
are a common source of NullPointerExceptions. By using

Scan to Download
methods like isPresent to check for a value or map to
transform contained values, developers can avoid direct null
checks that often lead to runtime errors. The chapter
emphasizes defensive checking techniques that can further
mitigate the risks associated with null usage, thereby
enhancing program stability.

3.Question
Can you explain how to chain Optional objects using the
flatMap method?
Answer:Chaining Optionals with flatMap allows developers
to elegantly handle transformations that could also result in
absent values without nesting Optionals. For instance, if you
have an Optional containing a value that might yield another
Optional during processing, using flatMap flattens the result,
avoiding an Optional of Optional scenario. This helps in
building fluent APIs where you can seamlessly propagate
transformations while managing potential absence of values
effectively.

4.Question

Scan to Download
What are some practical examples provided in the
chapter for using Optionals?
Answer:The chapter provides multiple practical examples
including utilizing Optional to safely extract values from
collections, transforming user input where errors or absence
are likely, and demonstrating the use of Optional with
streams for data manipulation. Each example reinforces the
idea of using Optionals for clearer and safer handling of
values, especially in situations where null might previously
have been used.

5.Question
What is the significance of understanding
NullPointerExceptions when using Optionals?
Answer:Understanding NullPointerExceptions is essential
when adopting Optionals as they are designed to avoid this
issue by providing a clear contract for the presence or
absence of a value. This knowledge empowers developers to
write more predictable and robust code. The chapter
highlights how recognizing the pitfalls of null allows for

Scan to Download
better architectural choices in applications, ensuring
developers can leverage Optionals effectively to enhance
code quality and maintainability.

6.Question
How might knowledge gained from this chapter influence
one's approach to object-oriented design patterns?
Answer:Knowledge of Optionals and null handling can
profoundly influence object-oriented design patterns by
promoting principles of encapsulation and safety. Patterns
like the Factory or Strategy can incorporate Optionals in their
implementations to manage states or configurations that
might be absent, leading to cleaner code. For instance,
instead of returning null, a Factory could return an Optional,
indicating that an object may or may not have been created,
thus refining the pattern usage to be more robust against
null-related pitfalls.

7.Question
Could you discuss the concept of stream manipulation
with Optionals?

Scan to Download
Answer:The chapter explains how to manipulate a stream of
Optionals, including filtering out empty Optionals and
transforming their values. By applying functions like filter,
map, and flatMap directly on streams of Optionals,
developers can effectively manage collections that might
contain absent values, ensuring operations only proceed on
Non-empty states. This approach simplifies the handling of
potentially sparse data and enhances the expressiveness of
stream operations.
Chapter 45 | R| Q&A
1.Question
What are parallel streams, and how can they improve
performance in Java?
Answer:Parallel streams allow for concurrent
processing of collections in Java, leveraging multiple
cores of the CPU to perform operations faster. By
transforming standard sequential streams into
parallel streams, operations can be split and
executed in parallel, which significantly improves

Scan to Download
performance, especially for large data sets. For
instance, if you have a large list of numbers and
want to filter out primes, using a parallel stream can
complete the task much quicker than processing
each number sequentially.

2.Question
How does the concept of partitioning enhance data
manipulation in Java?
Answer:Partitioning in Java refers to the process of dividing
data into distinct groups based on certain criteria, allowing
for more efficient data processing. For example, you can split
a collection of numbers into prime and non-prime numbers
using a partitioning method. This not only simplifies
complex operations into manageable groups but also enables
targeted processing, such as applying different functions on
each partition, which can lead to improved performance and
cleaner code.

3.Question
What is the significance of pure functions in functional
programming within Java?

Scan to Download
Answer:Pure functions are crucial in functional programming
because they guarantee that the output of a function is solely
determined by its input values, without any side effects. This
predictability makes reasoning about code easier and
enhances testability. In Java, leveraging pure functions
simplifies debugging and concurrent programming, as the
absence of side effects allows for safe parallel execution
without the risk of data inconsistencies.

4.Question
Can you explain the role of the Publish-Subscribe model
in reactive programming?
Answer:The Publish-Subscribe model is central to reactive
programming as it facilitates a communication pattern where
publishers (data producers) send messages to subscribers
(data consumers) without directly coupling the two. This
decoupling enables systems to react to events asynchronously
and efficiently. For example, in a real-time stock market
application, data updates can be published to all subscribers,
ensuring that they receive timely information without waiting

Scan to Download
for responses from each other, thus enhancing responsiveness
and scalability.

5.Question
What advantages does using the Reactive Manifesto bring
to application development?
Answer:The Reactive Manifesto promotes principles of
responsive, resilient, elastic, and message-driven
architectures, which fundamentally enhances application
development. By adhering to these principles, developers can
build applications that are more responsive to user
interactions, self-healing in the face of failures, scalable to
accommodate varying loads, and effectively communicate
through asynchronous message passing, greatly improving
user experience and system reliability.

Scan to Download
Chapter 46 | S| Q&A
1.Question
What is reactive programming and how does it differ
from traditional programming models?
Answer:Reactive programming is a programming
paradigm oriented around data flows and the
propagation of change, allowing developers to create
applications that are responsive to user interactions
and asynchronous events. Unlike traditional
imperative programming models, which often rely
on a series of commands to change the state of an
application sequentially, reactive programming
emphasizes the use of observable streams of data.
This allows applications to react to data changes in
real-time without blocking the main execution
thread.

2.Question
What are Observables in the context of RxJava, and why
are they important?

Scan to Download
Answer:Observables are core components in the RxJava
library that represent a sequence of data that can be observed
over time. They enable asynchronous programming by
allowing developers to subscribe to these data streams and
react to new data events as they occur. This is crucial for
building responsive applications since it allows handling of
multiple asynchronous tasks simultaneously, improving the
overall user experience.

3.Question
Can you explain the concept of backpressure in reactive
programming and its significance?
Answer:Backpressure is a mechanism in reactive
programming that helps manage the flow of data between
producers and consumers. It prevents overwhelming
consumers by allowing them to signal to producers when
they need to slow down or stop sending data, thus
maintaining a balance. This is significant because it enhances
application performance and stability, particularly when
dealing with high-volume data streams or slow consumers.

Scan to Download
4.Question
How can one transform data using the Processor in
RxJava?
Answer:In RxJava, a Processor is a type of Subject that
allows both subscribing to and emitting data. It acts as an
intermediary, enabling the transformation of incoming data
before it reaches the final subscriber. For example, if you
have a stream of raw string data, you can use a Processor to
transform it into uppercase strings or to filter certain patterns
out before passing it to the subscribers. This allows for
dynamic data transformation within the reactive pipeline.

5.Question
What are some key advantages of adopting functional
programming styles in Java projects?
Answer:Adopting functional programming styles in Java
enhances code readability and maintainability by facilitating
clearer expression of logic through functions as first-class
citizens, and reducing side effects by using stateless, pure
functions. This typically leads to fewer bugs and easier

Scan to Download
debugging since functions have no reliance on the outside
state. Additionally, functional programming can improve
performance through lazy evaluation and enables the use of
parallel processing more efficiently.

6.Question
What is the role of the Flow class in Java's reactive
stream API?
Answer:The Flow class in Java's reactive streams API
represents the foundation for building asynchronous data
processing pipelines. It defines interfaces for publisher,
subscriber, and processor roles, laying out a standard
approach for handling data streams with backpressure
support. By following the Flow class structure, developers
can create a robust setup for managing asynchronous data
flows across applications, ensuring that different components
communicate efficiently.

7.Question
What are some common design patterns used in Java,
and why are they important in modern applications?

Scan to Download
Answer:Common design patterns in Java include the
Observer, Factory, Strategy, and Template Method patterns.
These patterns provide time-tested solutions to common
software design problems, enhancing code reusability,
flexibility, and scalability. They help developers to create
systems that can evolve over time without significant
rewrites, maintain separation of concerns, and encourage
good coding practices, ultimately resulting in more
maintainable and understandable codebases.

8.Question
How does the concept of referential transparency
improve code reliability?
Answer:Referential transparency is the property of functions
where the function can be replaced with its value without
changing the program's behavior. This means that functions
produce the same output for the same input without side
effects, making reasoning about code easier and more
predictable. In modern Java applications, adopting referential
transparency helps in building reliable, testable and

Scan to Download
maintainable code, as developers can treat functions as pure
mathematical functions, leading to fewer runtime errors.
Chapter 47 | T| Q&A
1.Question
What advantages do parallel streams offer in Java
programming?
Answer:Parallel streams in Java enable developers
to process data concurrently, which can significantly
enhance performance, especially when dealing with
large datasets. They utilize multiple cores of the
CPU to split the task into smaller chunks
automatically and process them in parallel. This
efficiency is particularly beneficial for numerical
operations or complex data transformations, making
it easier to write cleaner and more readable code
while leveraging modern multi-core processors.

2.Question
How can you measure the performance of streams in
Java?

Scan to Download
Answer:Performance measurement of streams can be
accomplished using the 'System.nanoTime()' method to
capture the start and end time of a stream operation. You can
wrap your stream processing logic within these time capture
points. This helps to understand the efficiency of both
sequential and parallel streams by comparing execution
times, allowing developers to make informed decisions on
which approach to use based on the size of the dataset and
complexity of operations.

3.Question
What is the purpose of using intermediate operations in
streams, and can you give an example?
Answer:Intermediate operations in streams serve to
transform the elements of a stream without consuming it;
they produce a new stream as a result. An example of an
intermediate operation is 'filter()', which selects elements that
match a given predicate. For instance, if you have a list of
numbers and want to find all even numbers, you could use
'numbers.stream().filter(n -> n % 2 == 0)'. This operation

Scan to Download
creates a new stream containing only those elements, while
the original stream remains unchanged.

4.Question
In what scenarios would you need to combine multiple
stream operations, and how can this be achieved?
Answer:Combining multiple stream operations is useful
when complex data processing is needed, such as filtering,
mapping, and then reducing data in a single pipeline. This
can be achieved by chaining the operations together, using
methods like 'filter()', 'map()', and 'reduce()' in sequence. For
example, you might first filter a collection of objects to only
include those that meet a certain criterion, then map those
objects to another form before finally reducing them to a
summary count or value.

5.Question
What is the role of the 'reduce' operation in stream
processing?
Answer:The 'reduce' operation in stream processing is pivotal
for aggregating or summarizing data. It takes a sequence of

Scan to Download
elements and combines them into a single result using a
specified binary operator. For instance, if you want to sum a
list of integers, you could use the reduce method:
'numbers.stream().reduce(0, Integer::sum)'. This operation
not only condenses the data but also demonstrates functional
programming principles, aligning with clean and expressive
code.

6.Question
Can you explain the significance of the 'Supplier'
functional interface in asynchronous programming in
Java?
Answer:The 'Supplier' functional interface is significant in
asynchronous programming as it represents a function that
does not take any arguments but returns a result. It is
commonly used in the context of asynchronous tasks, such as
with the 'CompletableFuture.supplyAsync()' method,
allowing developers to define tasks that can be executed in a
separate thread. This helps in creating non-blocking
applications, where the main thread can continue to operate

Scan to Download
while waiting for tasks to complete, leading to improved
responsiveness of applications.

7.Question
What are some disadvantages associated with using
threads directly as opposed to higher-level abstractions
like thread pools?
Answer:Using threads directly can lead to various
disadvantages, including increased complexity in thread
management, potential for resource exhaustion, and higher
overhead in creating and destroying threads. In contrast,
thread pools provide a reusable set of threads, reducing the
cost associated with thread creation and improving
performance by managing the allocation and lifecycle of
threads efficiently. This leads to better resource utilization
and simplifies concurrent programming.

8.Question
How does the 'StreamSupport.stream' method enhance
the functionality of streams in Java?
Answer:The 'StreamSupport.stream' method enhances stream
functionality by allowing the creation of streams from

Scan to Download
various data sources, such as arrays, collections, or even
custom sources. This flexibility means that developers can
easily create streams that adhere to the Java Streams API,
facilitating data processing across diverse data structures and
enhancing interoperability within the Java ecosystem. It is
particularly useful when dealing with data that does not
naturally conform to the standard stream creation methods.
Chapter 48 | Z| Q&A
1.Question
What practical challenges does Modern Java address for
developers?
Answer:Modern Java addresses the challenges of
implementing innovative designs such as
microservices, reactive architectures, and streaming
data in applications. It provides developers with
modern features like lambdas, streams, and the Java
Module System, making it significantly easier to
adapt to these new paradigms.

2.Question

Scan to Download
How do lambdas and the Streams API benefit code
readability and maintenance in Java?
Answer:Lambdas and the Streams API facilitate writing
concise and expressive code, allowing developers to perform
complex data manipulations without boilerplate code. This
leads to reduced verbosity, making the code easier to read
and understand, which in turn simplifies maintenance and
improves collaboration among team members.

3.Question
In what ways does the book Modern Java in Action
support skill enhancement for developers?
Answer:The book offers a thorough exploration of new
features in Java 8 and beyond, accompanied by clear
examples that bridge the gap between theoretical concepts
and practical applications. By expanding existing knowledge
of core Java and introducing modern features, it equips
developers with the tools necessary to stay ahead in the
evolving landscape of software development.

4.Question

Scan to Download
What is the significance of the Java Module System
mentioned in the book?
Answer:The Java Module System is significant as it
introduces modularization to the Java platform, allowing
developers to create well-encapsulated components and
improve the organization of codebases. This can lead to
better dependency management, enhanced security, and an
overall increase in application maintainability.

5.Question
What roles do Raoul-Gabriel Urma and his co-authors
play in the field of Java development?
Answer:Raoul-Gabriel Urma serves as the CEO of
Cambridge Spark, contributing significant insight into
modern educational practices in programming. Mario Fusco,
a senior software engineer at Red Hat, brings practical
expertise in software engineering, while Alan Mycroft, a
professor at the University of Cambridge, offers academic
perspectives on computer science and programming
paradigms.

Scan to Download
6.Question
Why is it important for Java developers to adopt modern
features and techniques as discussed in the book?
Answer:Adopting modern features and techniques is crucial
for Java developers to remain competitive in the job market
and industry. These features facilitate the development of
more efficient, scalable, and maintainable applications.
Furthermore, they help developers leverage new technologies
and frameworks that are becoming standard in contemporary
software development.

7.Question
How does the book address the transition from
traditional Java programming to modern practices?
Answer:The book gradually introduces readers to modern
practices by comparing traditional Java programming
techniques with new approaches, such as functional
programming concepts and the use of streams. It highlights
the differences and benefits of adopting modern patterns
through practical examples, making the transition smoother

Scan to Download
for developers.

Scan to Download
Modern Java in Action Quiz and Test
Check the Correct Answer on Bookey Website

Chapter 1 | How this book is organized: a roadmap|


Quiz and Test
1.Java 8 introduced lambda expressions to enable a
functional programming style.
2.The Streams API reduces performance compared to
standard Java collections.
3.The book 'Modern Java in Action' discusses enhancements
in Java 8 and Java 9.
Chapter 2 | Book forum| Quiz and Test
1.Java 8 introduced a transition towards
functional-style programming.
2.The appendices of the book contain only subjective
opinions and no concrete examples of Java features.
3.Purchasing the book gives readers access to a public forum
monitored by the authors for immediate responses.
Chapter 3 | 1 Java 8, 9, 10, and 11: what?s
happening?| Quiz and Test

Scan to Download
1.Java has remained stagnant since its release in
1996 and has not adapted to new computing needs.
2.Java 8 introduced the Streams API, which significantly
enhances the readability and performance of data
processing.
3.The Optional class, introduced in Java 9, was created to
eliminate the need for null references in Java applications.

Scan to Download
Chapter 4 | 2 Passing code with behavior
parameterization| Quiz and Test
1.Behavior parameterization allows for the
implementation of functions that can act on
varying instructions without modifying the
original code.
2.Lambda expressions in Java 8 increased the verbosity of
code compared to previous implementations using
anonymous classes.
3.The introduction of the ApplePredicate interface enhanced
flexibility but did not follow the strategy design pattern.
Chapter 5 | 3 Lambda expressions| Quiz and Test
1.Lambda expressions in Java 8 enhance code
flexibility and conciseness by enabling behavior
parameterization.
2.Lambda expressions can be utilized without the necessity
of functional interfaces in Java.
3.Java provides a variety of built-in functional interfaces
such as Predicate, Consumer, and Function for streamlined

Scan to Download
lambda usage.
Chapter 6 | 4 Introducing streams| Quiz and Test
1.Streams in Java allow for both parallel processing
and easy manipulation of data collections without
the need for multithreaded code.
2.In Java Streams, operations are executed immediately upon
chaining rather than waiting for a terminal operation to be
called.
3.Collections in Java are built on lazy evaluation, allowing
for deferred computation of values until they are needed.

Scan to Download
Chapter 7 | 5 Working with streams| Quiz and Test
1.The `filter` method can be used to create streams
of elements that match a specified condition in
Java.
2.The `distinct` method in Java Streams returns a stream
containing all elements, including duplicates.
3.Java's `flatMap` method is used to convert flat structures
into nested streams.
Chapter 8 | 6 Collecting data with streams| Quiz and
Test
1.Streams in Java 8 facilitate data collection and
manipulation using an imperative style.
2.The `collect` method in Streams is used for accumulating
results based on a standard interface provided by Java.
3.Custom collectors in Java streams cannot improve
performance and are harder to implement than traditional
collection methods.
Chapter 9 | 7 Parallel data processing and
performance| Quiz and Test
1.Developers can turn a collection into a parallel

Scan to Download
stream by using the method `parallelStream()`.
2.The Fork/Join Framework was introduced in Java 8 for
parallel processing.
3.Using shared mutable state in parallel streams is
recommended for better performance.

Scan to Download
Chapter 10 | 8 Collection API enhancements| Quiz
and Test
1.Java 9 introduces factory methods for creating
mutable lists, sets, and maps.
2.The method 'removeIf' was introduced in Java 8 to remove
elements from a collection based on a predicate.
3.ConcurrentHashMap provides improved performance for
concurrent operations compared to traditional synchronized
approaches.
Chapter 11 | 9 Refactoring, testing, and debugging|
Quiz and Test
1.Lambda expressions can replace verbose
anonymous classes in Java.
2.The Observer Pattern can only be implemented with
dedicated classes and cannot effectively use lambda
expressions.
3.Unit testing should focus on directly testing lambda
expressions rather than the methods they are used in.
Chapter 12 | 10 Domain-specific languages using
lambdas| Quiz and Test

Scan to Download
1.Domain-Specific Languages (DSLs) enhance
communication between technical and
non-technical stakeholders by using
domain-specific terminology.
2.All DSLs are built externally and require developing a
completely new syntax.
3.Java 8 features like lambda expressions hinder the
readability and maintainability of DSLs.

Scan to Download
Chapter 13 | 11 Using Optional as a better
alternative to null| Quiz and Test
1.Using null references in Java often leads to
NullPointerExceptions and decreased readability.
2.The Optional class in Java provides a way to handle
potential absence of values without using null references.
3.The Optional class is serializable and should be used
frequently in domain models without caution.
Chapter 14 | 12 New Date and Time API| Quiz and
Test
1.The new Date and Time API in Java 8 replaced
the old java.util.Date and java.util.Calendar
classes due to their significant limitations.
2.The Duration class in the new Date and Time API
measures time in seconds and hours only.
3.LocalDate and LocalTime in the new API can include time
zone information.
Chapter 15 | 13 Default methods| Quiz and Test
1.Default methods in Java 8 allow interfaces to
include method implementations.

Scan to Download
2.Adding a new method to an existing interface always
requires updates to all implementing classes.
3.When a class inherits multiple default methods with the
same signature, it must always override the method to
resolve ambiguities.

Scan to Download
Chapter 16 | 14 The Java Module System| Quiz and
Test
1.The Java Module System was introduced in Java 8
as part of Project Jigsaw.
2.The principle of Information Hiding emphasizes
minimizing dependencies by concealing implementation
details.
3.In the Java Module System, the `module-info.java` file
defines module dependencies and public APIs.
Chapter 17 | 15 Concepts behind
CompletableFuture and reactive programming|
Quiz and Test
1.Concurrency and parallelism refer to the same
concept in Java.
2.CompletableFuture allows for non-blocking operations
which improve efficiency in Java applications.
3.Reactive programming is the same as creating a reactive
system in Java.
Chapter 18 | 16 CompletableFuture: composable
asynchronous programming| Quiz and Test

Scan to Download
1.CompletableFuture was introduced in Java 8 to
enhance the Future interface for asynchronous
programming.
2.Future interface allows for expressing dependencies
between asynchronous tasks easily.
3.CompletableFuture includes methods like orTimeout and
completeOnTimeout for managing timeouts that were
introduced in Java 8.

Scan to Download
Chapter 19 | 17 Reactive programming| Quiz and
Test
1.Reactive programming is primarily concerned
with synchronous data processing.
2.The Reactive Manifesto includes the principle of being
responsive, which enhances user trust by ensuring
predictable response times.
3.Reactive programming only applies at the application level
and does not affect system-level structures.
Chapter 20 | 18 Thinking functionally| Quiz and Test
1.Functional programming emphasizes the use of
shared mutable data.
2.In functional programming, a pure function can produce
different outputs for the same input.
3.Declarative programming allows programmers to specify
what to achieve rather than how to achieve it.
Chapter 21 | 19 Functional programming
techniques| Quiz and Test
1.Java 8 introduced lambda expressions and method
references, allowing for easier handling of function

Scan to Download
values.
2.Persistent data structures in functional programming can be
modified after their creation.
3.Java supports native pattern matching similar to languages
like Scala.

Scan to Download
Chapter 22 | 20 Blending OOP and FP: Comparing
Java and Scala| Quiz and Test
1.Scala merges object-oriented programming (OOP)
and functional programming (FP), positioned as
an alternative to Java.
2.In Scala, collections are mutable by default, allowing for
classic data structure manipulation.
3.Scala supports currying, which simplifies the creation of
partially applied functions in its functional programming
paradigm.
Chapter 23 | 21 Conclusions and where next for
Java| Quiz and Test
1.Java 9 introduced a new module system that
hampers backward compatibility but improves
security and performance.
2.Java 10 introduced `var` as a keyword for specifying the
type of a variable, enabling type inference to reduce
boilerplate code.
3.The transition to shorter development cycles for Java
allows new features to be incorporated more quickly, with

Scan to Download
long-term support releases every three years.
Chapter 24 | A.1 Annotations| Quiz and Test
1.Java 8 allows multiple annotations of the same
type on a declaration without the need for
container annotations.
2.Type annotations in Java 8 can only be applied to method
parameters and return types.
3.The repeated annotations feature in Java 8 is achieved by
marking an annotation with @Repeatable and providing a
container annotation.

Scan to Download
Chapter 25 | A.2 Generalized target-type inference|
Quiz and Test
1.Java 8 comes with built-in annotations that
enhance type checking.
2.Generalized target-type inference improves type handling
in Java 8 by allowing for cleaner code without needing
explicit type declarations.
3.Prior to Java 8, target-type inference allowed for intuitive
type handling without the need for explicit type
declarations.
Chapter 26 | B.1 Collections| Quiz and Test
1.Java 8 introduced significant updates to the
Collections API including the addition of streams.
2.The Map interface in Java 8 includes new methods such as
getOrDefault and computeIfAbsent.
3.The removeIf method in the Collection interface is used to
add elements matching a predicate to a collection.
Chapter 27 | B.2 Concurrency| Quiz and Test
1.Java 8 introduced the CompletableFuture class as

Scan to Download
part of its concurrency updates.
2.ConcurrentHashMap uses an internal structure that
enhances performance by using oversized buckets to
improve retrieval time.
3.Java 8 allows Stream-like operations such as forEach and
reduce to be executed on ConcurrentHashMap without
locking its state.

Scan to Download
Chapter 28 | B.3 Arrays| Quiz and Test
1.The `reduceValues` method in
ConcurrentHashMap allows for maximum
parallelism when using a value of 1.
2.The `mappingCount` method in ConcurrentHashMap
returns the number of mappings as an int.
3.The new `parallelSort` method sorts arrays in parallel based
on a specified Comparator.
Chapter 29 | B.4 Number and Math| Quiz and Test
1.The `parallelPrefix` method can be used for the
parallel accumulation of array elements.
2.The Java `Number` class has no methods for performing
unsigned operations.
3.The `Math` class in Java does not provide any methods that
handle overflow checks for operations.
Chapter 30 | B.7 String| Quiz and Test
1.The Files class includes a method called Files.walk,
which can produce a recursive Stream<Path> with
configurable depth.

Scan to Download
2.The Reflection API updates include the introduction of the
java.lang.reflect.Executable class, which provides
functionality specific to methods only.
3.The String class has a new method called join that allows
for the concatenation of strings with a specified delimiter.

Scan to Download
Chapter 31 | C.1 Forking a stream| Quiz and Test
1.The StreamForker class allows the user to define
different operations for parallel processing on a
stream.
2.The ForkingStreamConsumer does not implement the
Consumer interface.
3.The getResults method of the StreamForker class is called
to trigger the execution of all defined operations on the
stream.
Chapter 32 | D.1 Anonymous classes| Quiz and Test
1.Lambda expressions can implement functional
interfaces just like anonymous classes.
2.Using lambda expressions instead of anonymous classes
can lead to performance issues due to increased numbers of
class files generated.
3.Every lambda expression creates a distinct subtype, making
it efficient for management when numerous expressions are
used.
Chapter 33 | D.2 Bytecode generation| Quiz and Test

Scan to Download
1.Bytecode generation can lead to various subtypes
of Comparator, which simplifies performance
optimizations by the JVM.
2.The command to inspect the bytecode of a class is `javap -c
-v ClassName`.
3.Java source files are executed directly by the JVM without
being compiled into bytecode.

Scan to Download
Chapter 34 | D.3 Invokedynamic to the rescue| Quiz
and Test
1.The compiler generates an anonymous class
named 'InnerClass$1' for implementations of the
Function interface.
2.Java 8's lambda expressions do not simplify the code
structure and still require an extra class for each function
implementation.
3.The 'invokedynamic' instruction was introduced in JDK7
and supports dynamically typed languages on the JVM.
Chapter 35 | D.4 Code-generation strategies| Quiz
and Test
1.The invokedynamic instruction delays the
translation of lambda expressions into bytecode
until runtime, allowing for future optimizations
while maintaining backward compatibility.
2.Stateless lambdas generate more performance overhead
compared to stateful lambdas due to their complex
translation requirements.
3.Captured variables in lambdas require the signature of the

Scan to Download
generated method to be modified to include extra
arguments representing the captured context.
Chapter 36 | A| Quiz and Test
1.The 'CompletableFutures' is an important part of
asynchronous programming in Java.
2.The 'Arrays.asSet' method is part of Java's standard library.
3.Nonblocking code is a key concept discussed in the context
of asynchronous programming in this chapter.

Scan to Download
Chapter 37 | C| Quiz and Test
1.The chapter discusses the Atomic Package &
Concurrency, which enhances thread safety and
performance in Java.
2.Behavior-Driven Development (BDD) does not use
annotations like @Before to provide testing features in
Java.
3.The Collectors API in Java only allows data to be summed,
but not grouped.
Chapter 38 | D| Quiz and Test
1.ConcurrentHashMap is designed to handle
ConcurrentModificationException effectively.
2.The Fork/Join Framework is not capable of measuring
performance of parallel streams.
3.Default Methods in Interfaces are only useful in simple
APIs without any evolution.
Chapter 39 | F| Quiz and Test
1.Domain-Specific Languages (DSLs) can only be
defined as external DSLs according to the chapter.

Scan to Download
2.The chapter emphasizes the importance of lambda
expressions in stream operations.
3.The ExecutorService interface is a part of the Executor
framework that deals solely with thread management
without any additional features.

Scan to Download
Chapter 40 | I| Quiz and Test
1.Function descriptors and functional interfaces are
unimportant in understanding functional
programming in Java.
2.The chapter discusses the differences between
object-oriented and functional programming styles,
highlighting the benefits of higher-order functions.
3.Lambda expressions, closures, and anonymous functions
are not considered first-class citizens in Java.
Chapter 41 | J| Quiz and Test
1.Java includes features such as default methods,
which provide a way to add new methods to
interfaces without breaking existing
implementations.
2.The Java module system allows only a single module to be
defined per JAR file.
3.Lambda expressions in Java are used to enable a functional
programming style, allowing behavior to be passed as
parameters.

Scan to Download
Chapter 42 | L| Quiz and Test
1.The chapter covers various classes and interfaces
available in the `java.util` package, focusing on
utilities for concurrency, functional programming,
and stream processing.
2.The `ForkJoinPool` class is part of the
`java.util.concurrent` package and is used primarily for
implementing the Observer design pattern.
3.Lambda expressions in Java allow for the creation of
concise and readable code, enabling behavior
parameterization and higher-order functions.

Scan to Download
Chapter 43 | N| Quiz and Test
1.The chapter discusses the use of
`LongAccumulator` and `LongAdder` classes to
improve performance in concurrent applications.
2.Java's Math class does not include mathematical functions
to simplify calculations.
3.The chapter includes an in-depth analysis of memoization
techniques as a method for improving code efficiency.
Chapter 44 | P| Quiz and Test
1.The Optional class is used to model the absence of
a value in Java.
2.Object-oriented design patterns are considered unnecessary
for improving code maintainability and scalability.
3.Parallel streams can be utilized for efficient parallel data
processing in Java.
Chapter 45 | R| Quiz and Test
1.The chapter discusses the use of the Predicate
interface exclusively for filtering and slicing
streams.

Scan to Download
2.The section on Reactive Systems Overview includes
principles of reactive programming like backpressure.
3.Partitioning data is only useful in the context of collections
of strings and not applicable to numeric collections.

Scan to Download
Chapter 46 | S| Quiz and Test
1.The RxJava Reactive Library includes creating
and using Observables as one of its key concepts.
2.The Strategy Pattern is a part of the Streams Overview
section in the chapter.
3.Functional programming is emphasized as a style in Scala
programming according to the chapter summary.
Chapter 47 | T| Quiz and Test
1.Streams in Java do not have numeric
specializations for ranges and operations.
2.The Visitor pattern is one of the design patterns discussed
in the chapter summary.
3.Slicing and skipping in stream manipulation do not involve
the use of predicates.
Chapter 48 | Z| Quiz and Test
1.Chapter 48 of 'Modern Java in Action' presents an
index of concepts related to modern Java
programming.
2.The chapter primarily focuses on Java 8 features and does

Scan to Download
not cover Java 9 or beyond.
3.The authors of the book have backgrounds exclusively in
academia with no industry experience.

Scan to Download

You might also like