logo资料库

Modern Java In Action 2019.pdf

第1页 / 共592页
第2页 / 共592页
第3页 / 共592页
第4页 / 共592页
第5页 / 共592页
第6页 / 共592页
第7页 / 共592页
第8页 / 共592页
资料共592页,剩余部分请下载后查看
Modern Java in Action
brief contents
contents
preface
acknowledgments
about this book
How this book is organized: a roadmap
About the code
Book forum
about the authors
about the cover illustration
Part 1?Fundamentals
1 Java 8, 9, 10, and 11: what?s happening?
1.1 So, what?s the big story?
1.2 Why is Java still changing?
1.2.1 Java?s place in the programming language ecosystem
1.2.2 Stream processing
1.2.3 Passing code to methods with behavior parameterization
1.2.4 Parallelism and shared mutable data
1.2.5 Java needs to evolve
1.3 Functions in Java
1.3.1 Methods and lambdas as first-class citizens
1.3.2 Passing code: an example
1.3.3 From passing methods to lambdas
1.4 Streams
1.4.1 Multithreading is difficult
1.5 Default methods and Java modules
1.6 Other good ideas from functional programming
Summary
2 Passing code with behavior parameterization
2.1 Coping with changing requirements
2.1.1 First attempt: filtering green apples
2.1.2 Second attempt: parameterizing the color
2.1.3 Third attempt: filtering with every attribute you can think of
2.2 Behavior parameterization
2.2.1 Fourth attempt: filtering by abstract criteria
2.3 Tackling verbosity
2.3.1 Anonymous classes
2.3.2 Fifth attempt: using an anonymous class
2.3.3 Sixth attempt: using a lambda expression
2.3.4 Seventh attempt: abstracting over List type
2.4 Real-world examples
2.4.1 Sorting with a Comparator
2.4.2 Executing a block of code with Runnable
2.4.3 Returning a result using Callable
2.4.4 GUI event handling
Summary
3 Lambda expressions
3.1 Lambdas in a nutshell
3.2 Where and how to use lambdas
3.2.1 Functional interface
3.2.2 Function descriptor
3.3 Putting lambdas into practice: the execute-around pattern
3.3.1 Step 1: Remember behavior parameterization
3.3.2 Step 2: Use a functional interface to pass behaviors
3.3.3 Step 3: Execute a behavior!
3.3.4 Step 4: Pass lambdas
3.4 Using functional interfaces
3.4.1 Predicate
3.4.2 Consumer
3.4.3 Function
3.5 Type checking, type inference, and restrictions
3.5.1 Type checking
3.5.2 Same lambda, different functional interfaces
3.5.3 Type inference
3.5.4 Using local variables
3.6 Method references
3.6.1 In a nutshell
3.6.2 Constructor references
3.7 Putting lambdas and method references into practice
3.7.1 Step 1: Pass code
3.7.2 Step 2: Use an anonymous class
3.7.3 Step 3: Use lambda expressions
3.7.4 Step 4: Use method references
3.8 Useful methods to compose lambda expressions
3.8.1 Composing Comparators
3.8.2 Composing Predicates
3.8.3 Composing Functions
3.9 Similar ideas from mathematics
3.9.1 Integration
3.9.2 Connecting to Java 8 lambdas
Summary
Part 2?Functional-style data processing with streams
4 Introducing streams
4.1 What are streams?
4.2 Getting started with streams
4.3 Streams vs. collections
4.3.1 Traversable only once
4.3.2 External vs. internal iteration
4.4 Stream operations
4.4.1 Intermediate operations
4.4.2 Terminal operations
4.4.3 Working with streams
4.5 Road map
Summary
5 Working with streams
5.1 Filtering
5.1.1 Filtering with a predicate
5.1.2 Filtering unique elements
5.2 Slicing a stream
5.2.1 Slicing using a predicate
5.2.2 Truncating a stream
5.2.3 Skipping elements
5.3 Mapping
5.3.1 Applying a function to each element of a stream
5.3.2 Flattening streams
5.4 Finding and matching
5.4.1 Checking to see if a predicate matches at least one element
5.4.2 Checking to see if a predicate matches all elements
5.4.3 Finding an element
5.4.4 Finding the first element
5.5 Reducing
5.5.1 Summing the elements
5.5.2 Maximum and minimum
5.6 Putting it all into practice
5.6.1 The domain: Traders and Transactions
5.6.2 Solutions
5.7 Numeric streams
5.7.1 Primitive stream specializations
5.7.2 Numeric ranges
5.7.3 Putting numerical streams into practice: Pythagorean triples
5.8 Building streams
5.8.1 Streams from values
5.8.2 Stream from nullable
5.8.3 Streams from arrays
5.8.4 Streams from files
5.8.5 Streams from functions: creating infinite streams!
5.9 Overview
Summary
6 Collecting data with streams
6.1 Collectors in a nutshell
6.1.1 Collectors as advanced reductions
6.1.2 Predefined collectors
6.2 Reducing and summarizing
6.2.1 Finding maximum and minimum in a stream of values
6.2.2 Summarization
6.2.3 Joining Strings
6.2.4 Generalized summarization with reduction
6.3 Grouping
6.3.1 Manipulating grouped elements
6.3.2 Multilevel grouping
6.3.3 Collecting data in subgroups
6.4 Partitioning
6.4.1 Advantages of partitioning
6.4.2 Partitioning numbers into prime and nonprime
6.5 The Collector interface
6.5.1 Making sense of the methods declared by Collector interface
6.5.2 Putting them all together
6.6 Developing your own collector for better performance
6.6.1 Divide only by prime numbers
6.6.2 Comparing collectors? performances
Summary
7 Parallel data processing and performance
7.1 Parallel streams
7.1.1 Turning a sequential stream into a parallel one
7.1.2 Measuring stream performance
7.1.3 Using parallel streams correctly
7.1.4 Using parallel streams effectively
7.2 The fork/join framework
7.2.1 Working with RecursiveTask
7.2.2 Best practices for using the fork/join framework
7.2.3 Work stealing
7.3 Spliterator
7.3.1 The splitting process
7.3.2 Implementing your own Spliterator
Summary
Part 3?Effective programming with streams and lambdas
8 Collection API enhancements
8.1 Collection factories
8.1.1 List factory
8.1.2 Set factory
8.1.3 Map factories
8.2 Working with List and Set
8.2.1 removeIf
8.2.2 replaceAll
8.3 Working with Map
8.3.1 forEach
8.3.2 Sorting
8.3.3 getOrDefault
8.3.4 Compute patterns
8.3.5 Remove patterns
8.3.6 Replacement patterns
8.3.7 Merge
8.4 Improved ConcurrentHashMap
8.4.1 Reduce and Search
8.4.2 Counting
8.4.3 Set views
Summary
9 Refactoring, testing, and debugging
9.1 Refactoring for improved readability and flexibility
9.1.1 Improving code readability
9.1.2 From anonymous classes to lambda expressions
9.1.3 From lambda expressions to method references
9.1.4 From imperative data processing to Streams
9.1.5 Improving code flexibility
9.2 Refactoring object-oriented design patterns with lambdas
9.2.1 Strategy
9.2.2 Template method
9.2.3 Observer
9.2.4 Chain of responsibility
9.2.5 Factory
9.3 Testing lambdas
9.3.1 Testing the behavior of a visible lambda
9.3.2 Focusing on the behavior of the method using a lambda
9.3.3 Pulling complex lambdas into separate methods
9.3.4 Testing high-order functions
9.4 Debugging
9.4.1 Examining the stack trace
9.4.2 Logging information
Summary
10 Domain-specific languages using lambdas
10.1 A specific language for your domain
10.1.1 Pros and cons of DSLs
10.1.2 Different DSL solutions available on the JVM
10.2 Small DSLs in modern Java APIs
10.2.1 The Stream API seen as a DSL to manipulate collections
10.2.2 Collectors as a DSL to aggregate data
10.3 Patterns and techniques to create DSLs in Java
10.3.1 Method chaining
10.3.2 Using nested functions
10.3.3 Function sequencing with lambda expressions
10.3.4 Putting it all together
10.3.5 Using method references in a DSL
10.4 Real World Java 8 DSL
10.4.1 jOOQ
10.4.2 Cucumber
10.4.3 Spring Integration
Summary
Part 4?Everyday Java
11 Using Optional as a better alternative to null
11.1 How do you model the absence of a value?
11.1.1 Reducing NullPointerExceptions with defensive checking
11.1.2 Problems with null
11.1.3 What are the alternatives to null in other languages?
11.2 Introducing the Optional class
11.3 Patterns for adopting Optionals
11.3.1 Creating Optional objects
11.3.2 Extracting and transforming values from Optionals with map
11.3.3 Chaining Optional objects with flatMap
11.3.4 Manipulating a stream of optionals
11.3.5 Default actions and unwrapping an Optional
11.3.6 Combining two Optionals
11.3.7 Rejecting certain values with filter
11.4 Practical examples of using Optional
11.4.1 Wrapping a potentially null value in an Optional
11.4.2 Exceptions vs. Optional
11.4.3 Primitive optionals and why you shouldn?t use them
11.4.4 Putting it all together
Summary
12 New Date and Time API
12.1 LocalDate, LocalTime, LocalDateTime, Instant, Duration, and Period
12.1.1 Working with LocalDate and LocalTime
12.1.2 Combining a date and a time
12.1.3 Instant: a date and time for machines
12.1.4 Defining a Duration or a Period
12.2 Manipulating, parsing, and formatting dates
12.2.1 Working with TemporalAdjusters
12.2.2 Printing and parsing date-time objects
12.3 Working with different time zones and calendars
12.3.1 Using time zones
12.3.2 Fixed offset from UTC/Greenwich
12.3.3 Using alternative calendar systems
Summary
13 Default methods
13.1 Evolving APIs
13.1.1 API version 1
13.1.2 API version 2
13.2 Default methods in a nutshell
13.3 Usage patterns for default methods
13.3.1 Optional methods
13.3.2 Multiple inheritance of behavior
13.4 Resolution rules
13.4.1 Three resolution rules to know
13.4.2 Most specific default-providing interface wins
13.4.3 Conflicts and explicit disambiguation
13.4.4 Diamond problem
Summary
14 The Java Module System
14.1 The driving force: reasoning about software
14.1.1 Separation of concerns
14.1.2 Information hiding
14.1.3 Java software
14.2 Why the Java Module System was designed
14.2.1 Modularity limitations
14.2.2 Monolithic JDK
14.2.3 Comparison with OSGi
14.3 Java modules: the big picture
14.4 Developing an application with the Java Module System
14.4.1 Setting up an application
14.4.2 Fine-grained and coarse-grained modularization
14.4.3 Java Module System basics
14.5 Working with several modules
14.5.1 The exports clause
14.5.2 The requires clause
14.5.3 Naming
14.6 Compiling and packaging
14.7 Automatic modules
14.8 Module declaration and clauses
14.8.1 requires
14.8.2 exports
14.8.3 requires transitive
14.8.4 exports to
14.8.5 open and opens
14.8.6 uses and provides
14.9 A bigger example and where to learn more
Summary
Part 5?Enhanced Java concurrency
15 Concepts behind CompletableFuture and reactive programming
15.1 Evolving Java support for expressing concurrency
15.1.1 Threads and higher-level abstractions
15.1.2 Executors and thread pools
15.1.3 Other abstractions of threads: non-nested with method calls
15.1.4 What do you want from threads?
15.2 Synchronous and asynchronous APIs
15.2.1 Future-style API
15.2.2 Reactive-style API
15.2.3 Sleeping (and other blocking operations) considered harmful
15.2.4 Reality check
15.2.5 How do exceptions work with asynchronous APIs?
15.3 The box-and-channel model
15.4 CompletableFuture and combinators for concurrency
15.5 Publish-subscribe and reactive programming
15.5.1 Example use for summing two flows
15.5.2 Backpressure
15.5.3 A simple form of real backpressure
15.6 Reactive systems vs. reactive programming
15.7 Road map
Summary
16 CompletableFuture: composable asynchronous programming
16.1 Simple use of Futures
16.1.1 Understanding Futures and their limitations
16.1.2 Using CompletableFutures to build an asynchronous application
16.2 Implementing an asynchronous API
16.2.1 Converting a synchronous method into an asynchronous one
16.2.2 Dealing with errors
16.3 Making your code nonblocking
16.3.1 Parallelizing requests using a parallel Stream
16.3.2 Making asynchronous requests with CompletableFutures
16.3.3 Looking for the solution that scales better
16.3.4 Using a custom Executor
16.4 Pipelining asynchronous tasks
16.4.1 Implementing a discount service
16.4.2 Using the Discount service
16.4.3 Composing synchronous and asynchronous operations
16.4.4 Combining two CompletableFutures: dependent and independent
16.4.5 Reflecting on Future vs. CompletableFuture
16.4.6 Using timeouts effectively
16.5 Reacting to a CompletableFuture completion
16.5.1 Refactoring the best-price-finder application
16.5.2 Putting it all together
16.6 Road map
Summary
17 Reactive programming
17.1 The Reactive Manifesto
17.1.1 Reactive at application level
17.1.2 Reactive at system level
17.2 Reactive streams and the Flow API
17.2.1 Introducing the Flow class
17.2.2 Creating your first reactive application
17.2.3 Transforming data with a Processor
17.2.4 Why doesn?t Java provide an implementation of the Flow API?
17.3 Using the reactive library RxJava
17.3.1 Creating and using an Observable
17.3.2 Transforming and combining Observables
Summary
Part 6?Functional programming and future Java evolution
18 Thinking functionally
18.1 Implementing and maintaining systems
18.1.1 Shared mutable data
18.1.2 Declarative programming
18.1.3 Why functional programming?
18.2 What?s functional programming?
18.2.1 Functional-style Java
18.2.2 Referential transparency
18.2.3 Object-oriented vs. functional-style programming
18.2.4 Functional style in practice
18.3 Recursion vs. iteration
Summary
19 Functional programming techniques
19.1 Functions everywhere
19.1.1 Higher-order functions
19.1.2 Currying
19.2 Persistent data structures
19.2.1 Destructive updates vs. functional
19.2.2 Another example with Trees
19.2.3 Using a functional approach
19.3 Lazy evaluation with streams
19.3.1 Self-defining stream
19.3.2 Your own lazy list
19.4 Pattern matching
19.4.1 Visitor design pattern
19.4.2 Pattern matching to the rescue
19.5 Miscellany
19.5.1 Caching or memoization
19.5.2 What does ?Return the same object? mean?
19.5.3 Combinators
Summary
20 Blending OOP and FP: Comparing Java and Scala
20.1 Introduction to Scala
20.1.1 Hello beer
20.1.2 Basic data structures: List, Set, Map, Tuple, Stream, Option
20.2 Functions
20.2.1 First-class functions in Scala
20.2.2 Anonymous functions and closures
20.2.3 Currying
20.3 Classes and traits
20.3.1 Less verbosity with Scala classes
20.3.2 Scala traits vs. Java interfaces
Summary
21 Conclusions and where next for Java
21.1 Review of Java 8 features
21.1.1 Behavior parameterization (lambdas and method references)
21.1.2 Streams
21.1.3 CompletableFuture
21.1.4 Optional
21.1.5 Flow API
21.1.6 Default methods
21.2 The Java 9 module system
21.3 Java 10 local variable type inference
21.4 What?s ahead for Java?
21.4.1 Declaration-site variance
21.4.2 Pattern matching
21.4.3 Richer forms of generics
21.4.4 Deeper support for immutability
21.4.5 Value types
21.5 Moving Java forward faster
21.6 The final word
Appendix A?Miscellaneous language updates
A.1 Annotations
A.1.1 Repeated annotations
A.1.2 Type annotations
A.2 Generalized target-type inference
Appendix B?Miscellaneous library updates
B.1 Collections
B.1.1 Additional methods
B.1.2 The Collections class
B.1.3 Comparator
B.2 Concurrency
B.2.1 Atomic
B.2.2 ConcurrentHashMap
B.3 Arrays
B.3.1 Using parallelSort
B.3.2 Using setAll and parallelSetAll
B.3.3 Using parallelPrefix
B.4 Number and Math
B.4.1 Number
B.4.2 Math
B.5 Files
B.6 Reflection
B.7 String
Appendix C?Performing multiple operations in parallel on a stream
C.1 Forking a stream
C.1.1 Implementing the Results interface with the ForkingStreamConsumer
C.1.2 Developing the ForkingStreamConsumer and the BlockingQueueSpliterator
C.1.3 Putting the StreamForker to work
C.2 Performance considerations
Appendix D?Lambdas and JVM bytecode
D.1 Anonymous classes
D.2 Bytecode generation
D.3 Invokedynamic to the rescue
D.4 Code-generation strategies
index
Symbols
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
Z
Lambdas, streams, functional and reactive programming IN ACTION Raoul-Gabriel Urma Mario Fusco Alan Mycroft M A N N I N G
Praise for the previous edition, Java 8 in Action, by Raoul-Gabriel Urma, Mario Fusco, and Alan Mycroft. A great and concise guide to what’s new in Java 8, with plenty of examples to get you going in a hurry. —Jason Lee, Oracle The best guide to Java 8 that will ever be written! —William Wheeler, ProData Computer Systems The new Streams API and lambda examples are especially useful. —Steve Rogers, CGTek, Inc. A must-have to get functional with Java 8. —Mayur S. Patil, MIT Academy of Engineering Helpful as a concise, practice-oriented guide to the exciting new features of Java 8. Functional interfaces and spliterators, oh my! —Will Hayworth, Developer, Atlassian
Modern Java in Action LAMBDAS, STREAMS, FUNCTIONAL AND REACTIVE PROGRAMMING RAOUL-GABRIEL URMA, MARIO FUSCO, AND ALAN MYCROFT M A N N I N G SHELTER ISLAND
For online information and ordering of this and other Manning books, please visit www.manning.com. The publisher offers discounts on this book when ordered in quantity. For more information, please contact Special Sales Department Manning Publications Co. 20 Baldwin Road PO Box 761 Shelter Island, NY 11964 Email: orders@manning.com ©2019 by Manning Publications Co. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by means electronic, mechanical, photocopying, or otherwise, without prior written permission of the publisher. Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in the book, and Manning Publications was aware of a trademark claim, the designations have been printed in initial caps or all caps. Recognizing the importance of preserving what has been written, it is Manning’s policy to have the books we publish printed on acid-free paper, and we exert our best efforts to that end. Recognizing also our responsibility to conserve the resources of our planet, Manning books are printed on paper that is at least 15 percent recycled and processed without the use of elemental chlorine. Manning Publications Co. 20 Baldwin Road PO Box 761 Shelter Island, NY 11964 Development editor: Kevin Harreld Technical development editor: Dennis Sellinger Review editor: Aleksandar Dragosavljevic´ Project manager: Deirdre Hiam Copy editors: Heidi Ward and Kathy Simpson Proofreader: Carol Shields Technical proofreader: Jean-François Morin Typesetter: Dennis Dalinnik Cover designer: Marija Tudor ISBN: 9781617293566 Printed in the United States of America 1 2 3 4 5 6 7 8 9 10 – DP – 23 22 21 20 19 18
brief contents PART 1 FUNDAMENTALS ............................................................1 Java 8, 9, 10, and 11: what’s happening? 3 1 ■ 2 ■ Passing code with behavior parameterization 26 3 ■ Lambda expressions 42 PART 2 FUNCTIONAL-STYLE DATA PROCESSING WITH STREAMS ... 79 Introducing streams 81 4 ■ 5 ■ Working with streams 98 6 ■ Collecting data with streams 134 7 ■ Parallel data processing and performance 172 PART 3 EFFECTIVE PROGRAMMING WITH STREAMS AND LAMBDAS............................................................199 8 ■ Collection API enhancements 201 9 ■ Refactoring, testing, and debugging 216 10 ■ Domain-specific languages using lambdas 239 v
vi BRIEF CONTENTS PART 4 EVERYDAY JAVA .........................................................273 11 ■ Using Optional as a better alternative to null 275 12 ■ New Date and Time API 297 13 ■ Default methods 314 14 ■ The Java Module System 333 PART 5 ENHANCED JAVA CONCURRENCY ................................355 15 ■ Concepts behind CompletableFuture and reactive programming 357 16 ■ CompletableFuture: composable asynchronous programming 387 17 ■ Reactive programming 416 PART 6 FUNCTIONAL PROGRAMMING AND FUTURE JAVA EVOLUTION...............................................................443 18 ■ Thinking functionally 445 19 ■ Functional programming techniques 460 20 ■ Blending OOP and FP: Comparing Java and Scala 485 21 ■ Conclusions and where next for Java 500
contents xix xxviii preface acknowledgments about this book about the authors about the cover illustration xxx xxi xxiii PART 1 FUNDAMENTALS ..................................................1 1 Java 8, 9, 10, and 11: what’s happening? 3 1.1 1.2 Why is Java still changing? 6 So, what’s the big story? 3 Java’s place in the programming language ecosystem 6 Stream processing 8 ■ Passing code to methods with behavior parameterization 9 ■ Parallelism and shared mutable data 10 Java needs to evolve 11 1.3 Functions in Java 12 Methods and lambdas as first-class citizens 12 ■ Passing code: an example 14 ■ From passing methods to lambdas 16 1.4 Streams 17 Multithreading is difficult 19 vii
分享到:
收藏