A Functional Approach to Java: Augmenting Object-Oriented Java Code with Functional Principles [1 ed.] 1098109929, 9781098109929

Java developers usually tackle the complexity of software development through object-oriented programming (OOP). But not

340 43 5MB

English Pages 400 Year 2023

Report DMCA / Copyright

DOWNLOAD FILE

A Functional Approach to Java: Augmenting Object-Oriented Java Code with Functional Principles [1 ed.]
 1098109929, 9781098109929

  • Commentary
  • Revision History for the First Edition: 2023-05-09: First Release

Table of contents :
Preface
New Hardware Needs a New Way of Thinking
Java Can Be Functional, Too
Why I Wrote This Book
Who Should Read This Book
What You Will Learn
What about Android?
A Functional Approach to Android
Navigating This Book
Conventions Used in This Book
Using Code Examples
O’Reilly Online Learning
Acknowledgments
I. Functional Basics
1. An Introduction to Functional Programming
What Makes a Language Functional?
Functional Programming Concepts
Pure Functions and Referential Transparency
Immutability
Recursion
First-Class and Higher-Order Functions
Functional Composition
Currying
Partial Function Application
Lazy Evaluation
Advantages of Functional Programming
Disadvantages of Functional Programming
Takeaways
2. Functional Java
What Are Java Lambdas?
Lambda Syntax
Functional Interfaces
Lambdas and Outside Variables
What about Anonymous Classes?
Lambdas in Action
Creating Lambdas
Calling Lambdas
Method References
Functional Programming Concepts in Java
Pure Functions and Referential Transparency
Immutability
First-Class Citizenship
Functional Composition
Lazy Evaluation
Takeaways
3. Functional Interfaces of the JDK
The Big Four Functional Interface Categories
Functions
Consumers
Suppliers
Predicates
Why So Many Functional Interface Variants?
Function Arity
Primitive Types
Bridging Functional Interfaces
Functional Composition
Extending Functional Support
Adding Default Methods
Implementing Functional Interfaces Explicitly
Creating Static Helpers
Takeaways
II. A Functional Approach
4. Immutability
Mutability and Data Structures in OOP
Immutability (Not Only) in FP
The State of Java Immutability
java.lang.String
Immutable Collections
Primitives and Primitive Wrappers
Immutable Math
Java Time API (JSR-310)
Enums
The final Keyword
Records
How to Achieve Immutability
Common Practices
Takeaways
5. Working with Records
Data Aggregation Types
Tuples
A Simple POJO
From POJO to Immutability
From POJO to Record
Records to the Rescue
Behind the Scenes
Record Features
Missing Features
Use Cases and Common Practices
Record Validation and Data Scrubbing
Increasing Immutability
Creating Modified Copies
Records as Local Nominal Tuples
Better Optional Data Handling
Serializing Evolving Records
Record Pattern Matching (Java 19+)
Final Thoughts on Records
Takeaways
6. Data Processing with Streams
Data Processing with Iteration
External Iteration
Internal Iteration
Streams as Functional Data Pipelines
Stream Features
Spliterator, the Backbone of Streams
Building Stream Pipelines
Creating a Stream
Doing the Work
Terminating the Stream
The Cost of Operations
Modifying Stream Behavior
To Use a Stream, or Not?
Takeaways
7. Working with Streams
Primitive Streams
Iterative Streams
Infinite Streams
Random Numbers
Memory Isn’t Infinite
From Arrays to Streams and Back
Object-Type Arrays
Primitive Arrays
Low-Level Stream Creation
Working with File I/O
Reading Directory Contents
Depth-First Directory Traversal
Searching the Filesystem
Reading Files Line-By-Line
Caveats of File I/O Streams
Dealing with Date and Time
Querying Temporal Types
LocalDate-Range Streams
Measuring Stream Performance with JMH
More about Collectors
Downstream Collectors
Creating Your Own Collector
Final Thoughts on (Sequential) Streams
Takeaways
8. Parallel Data Processing with Streams
Concurrency versus Parallelism
Streams as Parallel Functional Pipelines
Parallel Streams in Action
When to Use and When to Avoid Parallel Streams
Choosing the Right Data Source
Number of Elements
Stream Operations
Stream Overhead and Available Resources
Example: War and Peace (revisited)
Example: Random Numbers
Parallel Streams Checklist
Takeaways
9. Handling null with Optionals
The Problem with null References
How to Handle null in Java (Before Optionals)
Best Practices for Handling null
Tool-Assisted null Checks
Specialized Types Like Optional
Optionals to the Rescue
What’s an Optional?
Building Optional Pipelines
Optionals and Streams
Optionals as Stream Elements
Terminal Stream Operations
Optional Primitives
Caveats
Optionals Are Ordinary Types
Identity-Sensitive Methods
Performance Overhead
Special Considerations for Collections
Optionals and Serialization
Final Thoughts on null References
Takeaways
10. Functional Exception Handling
Java Exception Handling in a Nutshell
The try-catch block
The Different Types of Exceptions and Errors
Checked Exceptions in Lambdas
Safe Method Extraction
Un-Checking Exceptions
Sneaky Throws
A Functional Approach to Exceptions
Not Throwing Exceptions
Errors as Values
The Try/Success/Failure Pattern
Final Thoughts on Functional Exception Handling
Takeaways
11. Lazy Evaluation
Laziness Versus Strictness
How Strict Is Java?
Short-Circuit Evaluation
Control Structures
Lazy Types in the JDK
Lambdas and Higher-Order Functions
An Eager Approach
A Lazier Approach
A Functional Approach
Delayed Executions with Thunks
Creating a Simple Thunk
A Thread-Safe Thunk
Final Thoughts on Laziness
Takeaways
12. Recursion
What Is Recursion?
Head Versus Tail Recursion
Recursion and the Call Stack
A More Complex Example
Iterative Tree Traversal
Recursive Tree Traversal
Recursion-Like Streams
Final Thoughts on Recursion
Takeaways
13. Asynchronous Tasks
Synchronous versus Asynchronous
Java Futures
Designing Asynchronous Pipelines with CompletableFutures
Promising a Value
Creating a CompletableFuture
Compositing and Combining Tasks
Exception Handling
Terminal Operations
Creating a CompletableFuture Helper
Manual Creation and Completion
Manual Creation
Manual Completion
Use Cases for Manually Created and Completed Instances
About Thread Pools and Timeouts
Final Thoughts on Asynchronous Tasks
Takeaways
14. Functional Design Patterns
What Are Design Patterns?
(Functional) Design Patterns
Factory Pattern
Decorator Pattern
Strategy Pattern
Builder Pattern
Final Thoughts on Functional Design Patterns
Takeaways
15. A Functional Approach to Java
OOP Versus FP Principles
A Functional Mindset
Functions Are First-Class Citizens
Avoiding Side Effects
Functional Data Processing with Map/Filter/Reduce
Abstractions Guide Implementations
Building Functional Bridges
Parallelism and Concurrency Made Easy
Be Mindful of Potential Overhead
Functional Architecture in an Imperative World
From Objects to Values
Separation of Concerns
The Different Sizes of an FC/IS
Testing an FC/IS
Final Thoughts on a Functional Approach to Java
Takeaways
Index
About the Author

Polecaj historie