Core Java Vol Iiadvanced Features 12th Edition Cay S Horstmann
Core Java Vol Iiadvanced Features 12th Edition Cay S Horstmann
Core Java Vol Iiadvanced Features 12th Edition Cay S Horstmann
Core Java Vol Iiadvanced Features 12th Edition Cay S Horstmann
1. Core Java Vol Iiadvanced Features 12th Edition
Cay S Horstmann download
https://ebookbell.com/product/core-java-vol-iiadvanced-
features-12th-edition-cay-s-horstmann-49554648
Explore and download more ebooks at ebookbell.com
2. Here are some recommended products that we believe you will be
interested in. You can click the link to download.
Core Java Vol Iiadvanced Features 12th Edition Cay S Horstmann
https://ebookbell.com/product/core-java-vol-iiadvanced-features-12th-
edition-cay-s-horstmann-38321494
Core Java Volume Ii Advanced Features 11th Vol Ii Cay Horstmann
https://ebookbell.com/product/core-java-volume-ii-advanced-
features-11th-vol-ii-cay-horstmann-9992752
Core Java Vol 1 2 For The Impatient And Effective Pack 12th Ed Cay S
Horstmann
https://ebookbell.com/product/core-java-vol-1-2-for-the-impatient-and-
effective-pack-12th-ed-cay-s-horstmann-50687482
Core Java Volume I Fundamentals 12th Horstmann Cay
https://ebookbell.com/product/core-java-volume-i-fundamentals-12th-
horstmann-cay-46173296
3. Core Java Volume Ii Advanced Features 12th Cay S Horstmann
https://ebookbell.com/product/core-java-volume-ii-advanced-
features-12th-cay-s-horstmann-46173298
Core Java For The Impatient 3rd Edition Cay Horstmann
https://ebookbell.com/product/core-java-for-the-impatient-3rd-edition-
cay-horstmann-48456364
Core Java Interview Questions Youll Most Likely Be Asked Job Interview
Questions Series 2nd Edition Vibrant Publishers
https://ebookbell.com/product/core-java-interview-questions-youll-
most-likely-be-asked-job-interview-questions-series-2nd-edition-
vibrant-publishers-49183978
Core Java Made Simple Som Prakash Rai
https://ebookbell.com/product/core-java-made-simple-som-prakash-
rai-49422914
Core Java Volume Ifundamentals Cay S Horstmann
https://ebookbell.com/product/core-java-volume-ifundamentals-cay-s-
horstmann-49541448
6. Core Java, Vol. II-Advanced
Features
12th Edition
Cay S. Horstmann
7. Contents
Preface
Acknowledgments
Chapter 1: Streams
Chapter 2: Input and Output
Chapter 3: XML
Chapter 4: Networking
Chapter 5: Database Programming
Chapter 6: The Date and Time API
Chapter 7: Internationalization
Chapter 8: Scripting, Compiling, and Annotation Processing
Chapter 9: The Java Platform Module System
Chapter 10: Security
Chapter 11: Advanced Swing and Graphics
Chapter 12: Native Methods
8. Table of Contents
Preface
Acknowledgments
Chapter 1: Streams
1.1 From Iterating to Stream Operations
1.2 Stream Creation
1.3 The filter, map, and flatMap Methods
1.4 Extracting Substreams and Combining Streams
1.5 Other Stream Transformations
1.6 Simple Reductions
1.7 The Optional Type
1.7.1 Getting an Optional Value
1.7.2 Consuming an Optional Value
1.7.3 Pipelining Optional Values
1.7.4 How Not to Work with Optional Values
1.7.5 Creating Optional Values
1.7.6 Composing Optional Value Functions with flatMap
1.7.7 Turning an Optional into a Stream
1.8 Collecting Results
1.9 Collecting into Maps
1.10 Grouping and Partitioning
9. 1.11 Downstream Collectors
1.12 Reduction Operations
1.13 Primitive Type Streams
1.14 Parallel Streams
Chapter 2: Input and Output
2.1 Input/Output Streams
2.1.1 Reading and Writing Bytes
2.1.2 The Complete Stream Zoo
2.1.3 Combining Input/Output Stream Filters
2.1.4 Text Input and Output
2.1.5 How to Write Text Output
2.1.6 How to Read Text Input
2.1.7 Saving Objects in Text Format
2.1.8 Character Encodings
2.2 Reading and Writing Binary Data
2.2.1 The DataInput and DataOutput interfaces
2.2.2 Random-Access Files
2.2.3 ZIP Archives
2.3 Object Input/Output Streams and Serialization
2.3.1 Saving and Loading Serializable Objects
2.3.2 Understanding the Object Serialization File Format
2.3.3 Modifying the Default Serialization Mechanism
2.3.4 The readResolve and writeReplace methods
2.3.5 Versioning
2.3.6 Using Serialization for Cloning
2.3.7 Deserialization and Security
2.4 Working with Files
2.4.1 Paths
2.4.2 Reading and Writing Files
2.4.3 Creating Files and Directories
2.4.4 Copying, Moving, and Deleting Files
10. 2.4.5 Getting File Information
2.4.6 Visiting Directory Entries
2.4.7 Using Directory Streams
2.4.8 ZIP File Systems
2.5 Memory-Mapped Files
2.5.1 Memory-Mapped File Performance
2.5.2 The Buffer Data Structure
2.6 File Locking
2.7 Regular Expressions
2.7.1 The Regular Expression Syntax
2.7.2 Matching an Entire String
2.7.3 Finding All Matches in a String
2.7.4 Groups
2.7.5 Splitting along Delimiters
2.7.6 Replacing Matches
2.7.7 Flags
Chapter 3: XML
3.1 Introducing XML
3.2 The Structure of an XML Document
3.3 Parsing an XML Document
3.4 Validating XML Documents
3.4.1 Document Type Definitions
3.4.2 XML Schema
3.4.3 A Practical Example
3.5 Locating Information with XPath
3.6 Using Namespaces
3.7 Streaming Parsers
3.7.1 Using the SAX Parser
3.7.2 Using the StAX Parser
3.8 Generating XML Documents
3.8.1 Documents without Namespaces
11. 3.8.2 Documents with Namespaces
3.8.3 Writing Documents
3.8.4 Writing an XML Document with StAX
3.8.5 An Example: Generating an SVG File
3.9 XSL Transformations
Chapter 4: Networking
4.1 Connecting to a Server
4.1.1 Using Telnet
4.1.2 Connecting to a Server with Java
4.1.3 Socket Timeouts
4.1.4 Internet Addresses
4.2 Implementing Servers
4.2.1 Server Sockets
4.2.2 Serving Multiple Clients
4.2.3 Half-Close
4.2.4 Interruptible Sockets
4.3 Getting Web Data
4.3.1 URLs and URIs
4.3.2 Using a URLConnection to Retrieve Information
4.3.3 Posting Form Data
4.4 The HTTP Client
4.4.1 The HttpClient Class
4.4.2 The HttpRequest class and Body Publishers
4.4.3 The HttpResponse Interface and Body Handlers
4.4.4 Asynchronous Processing
4.5 Sending E-Mail
Chapter 5: Database Programming
5.1 The Design of JDBC
5.1.1 JDBC Driver Types
5.1.2 Typical Uses of JDBC
12. 5.2 The Structured Query Language
5.3 JDBC Configuration
5.3.1 Database URLs
5.3.2 Driver JAR Files
5.3.3 Starting the Database
5.3.4 Registering the Driver Class
5.3.5 Connecting to the Database
5.4 Working with JDBC Statements
5.4.1 Executing SQL Statements
5.4.2 Managing Connections, Statements, and Result Sets
5.4.3 Analyzing SQL Exceptions
5.4.4 Populating a Database
5.5 Query Execution
5.5.1 Prepared Statements
5.5.2 Reading and Writing LOBs
5.5.3 SQL Escapes
5.5.4 Multiple Results
5.5.5 Retrieving Autogenerated Keys
5.6 Scrollable and Updatable Result Sets
5.6.1 Scrollable Result Sets
5.6.2 Updatable Result Sets
5.7 Row Sets
5.7.1 Constructing Row Sets
5.7.2 Cached Row Sets
5.8 Metadata
5.9 Transactions
5.9.1 Programming Transactions with JDBC
5.9.2 Save Points
5.9.3 Batch Updates
5.9.4 Advanced SQL Types
5.10 Connection Management in Web and Enterprise Applications
13. Chapter 6: The Date and Time API
6.1 The Time Line
6.2 Local Dates
6.3 Date Adjusters
6.4 Local Time
6.5 Zoned Time
6.6 Formatting and Parsing
6.7 Interoperating with Legacy Code
Chapter 7: Internationalization
7.1 Locales
7.1.1 Why Locales?
7.1.2 Specifying Locales
7.1.3 The Default Locale
7.1.4 Display Names
7.2 Number Formats
7.2.1 Formatting Numeric Values
7.2.2 The DecimalFormat Class
7.2.3 Currencies
7.3 Date and Time
7.4 Collation and Normalization
7.5 Message Formatting
7.5.1 Formatting Numbers and Dates
7.5.2 Choice Formats
7.6 Text Input and Output
7.6.1 Text Files
7.6.2 Line Endings
7.6.3 The Console
7.6.4 Log Files
7.6.5 The UTF-8 Byte Order Mark
7.6.6 Character Encoding of Source Files
14. 7.7 Resource Bundles
7.7.1 Locating Resource Bundles
7.7.2 Property Files
7.7.3 Bundle Classes
7.8 A Complete Example
Chapter 8: Scripting, Compiling, and Annotation Processing
8.1 Scripting for the Java Platform
8.1.1 Getting a Scripting Engine
8.1.2 Script Evaluation and Bindings
8.1.3 Redirecting Input and Output
8.1.4 Calling Scripting Functions and Methods
8.1.5 Compiling a Script
8.1.6 An Example: Scripting GUI Events
8.2 The Compiler API
8.2.1 Invoking the Compiler
8.2.2 Launching a Compilation Task
8.2.3 Capturing Diagnostics
8.2.4 Reading Source Files from Memory
8.2.5 Writing Byte Codes to Memory
8.2.6 An Example: Dynamic Java Code Generation
8.3 Using Annotations
8.3.1 An Introduction into Annotations
8.3.2 An Example: Annotating Event Handlers
8.4 Annotation Syntax
8.4.1 Annotation Interfaces
8.4.2 Annotations
8.4.3 Annotating Declarations
8.4.4 Annotating Type Uses
8.4.5 Annotating this
8.5 Standard Annotations
8.5.1 Annotations for Compilation
15. 8.5.2 Meta-Annotations
8.6 Source-Level Annotation Processing
8.6.1 Annotation Processors
8.6.2 The Language Model API
8.6.3 Using Annotations to Generate Source Code
8.7 Bytecode Engineering
8.7.1 Modifying Class Files
8.7.2 Modifying Bytecodes at Load Time
Chapter 9: The Java Platform Module System
9.1 The Module Concept
9.2 Naming Modules
9.3 The Modular “Hello, World!” Program
9.4 Requiring Modules
9.5 Exporting Packages
9.6 Modular JARs
9.7 Modules and Reflective Access
9.8 Automatic Modules
9.9 The Unnamed Module
9.10 Command-Line Flags for Migration
9.11 Transitive and Static Requirements
9.12 Qualified Exporting and Opening
9.13 Service Loading
9.14 Tools for Working with Modules
Chapter 10: Security
10.1 Class Loaders
10.1.1 The Class-Loading Process
10.1.2 The Class Loader Hierarchy
10.1.3 Using Class Loaders as Namespaces
10.1.4 Writing Your Own Class Loader
10.1.5 Bytecode Verification
16. 10.2 User Authentication
10.2.1 The JAAS Framework
10.2.2 JAAS Login Modules
10.3 Digital Signatures
10.3.1 Message Digests
10.3.2 Message Signing
10.3.3 Verifying a Signature
10.3.4 The Authentication Problem
10.3.5 Certificate Signing
10.3.6 Certificate Requests
10.3.7 Code Signing
10.4 Encryption
10.4.1 Symmetric Ciphers
10.4.2 Key Generation
10.4.3 Cipher Streams
10.4.4 Public Key Ciphers
Chapter 11: Advanced Swing and Graphics
11.1 Tables
11.1.1 A Simple Table
11.1.2 Table Models
11.1.3 Working with Rows and Columns
11.1.3.1 Column Classes
11.1.3.2 Accessing Table Columns
11.1.3.3 Resizing Columns
11.1.3.4 Resizing Rows
11.1.3.5 Selecting Rows, Columns, and Cells
11.1.3.6 Sorting Rows
11.1.3.7 Filtering Rows
11.1.3.8 Hiding and Displaying Columns
11.1.4 Cell Rendering and Editing
11.1.4.1 Rendering Cells
17. 11.1.4.2 Rendering the Header
11.1.4.3 Editing Cells
11.1.4.4 Custom Editors
11.2 Trees
11.2.1 Simple Trees
11.2.1.1 Editing Trees and Tree Paths
11.2.2 Node Enumeration
11.2.3 Rendering Nodes
11.2.4 Listening to Tree Events
11.2.5 Custom Tree Models
11.3 Advanced AWT
11.3.1 The Rendering Pipeline
11.3.2 Shapes
11.3.2.1 The Shape Class Hierarchy
11.3.2.2 Using the Shape Classes
11.3.3 Areas
11.3.4 Strokes
11.3.5 Paint
11.3.6 Coordinate Transformations
11.3.7 Clipping
11.3.8 Transparency and Composition
11.4 Raster Images
11.4.1 Readers and Writers for Images
11.4.1.1 Obtaining Readers and Writers for Image File Types
11.4.1.2 Reading and Writing Files with Multiple Images
11.4.2 Image Manipulation
11.4.2.1 Constructing Raster Images
11.4.2.2 Filtering Images
11.5 Printing
11.5.1 Graphics Printing
11.5.2 Multiple-Page Printing
11.5.3 Print Services
18. 11.5.4 Stream Print Services
11.5.5 Printing Attributes
Chapter 12: Native Methods
12.1 Calling a C Function from a Java Program
12.2 Numeric Parameters and Return Values
12.3 String Parameters
12.4 Accessing Fields
12.4.1 Accessing Instance Fields
12.4.2 Accessing Static Fields
12.5 Encoding Signatures
12.6 Calling Java Methods
12.6.1 Instance Methods
12.6.2 Static Methods
12.6.3 Constructors
12.6.4 Alternative Method Invocations
12.7 Accessing Array Elements
12.8 Handling Errors
12.9 Using the Invocation API
12.10 A Complete Example: Accessing the Windows Registry
12.10.1 Overview of the Windows Registry
12.10.2 A Java Platform Interface for Accessing the Registry
12.10.3 Implementation of Registry Access Functions as Native
Methods
12.11 Foreign Functions: A Glimpse into the Future
19. Preface
To the Reader
The book you have in your hands is the second volume of the twelfth
edition of Core Java, fully updated for Java SE 17. The first volume covers
the essential features of the language; this volume deals with the advanced
topics that a programmer needs to know for professional software
development. Thus, as with the first volume and the previous editions of
this book, we are still targeting programmers who want to put Java
technology to work in real projects.
As is the case with any book, errors and inaccuracies are inevitable. Should
you find any in this book, we would very much like to hear about them. Of
course, we would prefer to hear about them only once. For this reason, we
have put up a web site at http://horstmann.com/corejava with a
FAQ, bug fixes, and workarounds. Strategically placed at the end of the bug
report web page (to encourage you to read the previous reports) is a form
that you can use to report bugs or problems and to send suggestions for
improvements for future editions.
About This Book
20. The chapters in this book are, for the most part, independent of each other.
You should be able to delve into whatever topic interests you the most and
read the chapters in any order.
In Chapter 1, you will learn all about the Java stream library that brings a
modern flavor to processing data, by specifying what you want without
describing in detail how the result should be obtained. This allows the
stream library to focus on an optimal evaluation strategy, which is
particularly advantageous for optimizing concurrent computations.
The topic of Chapter 2 is input and output handling (I/O). In Java, all input
and output is handled through input/output streams. These streams (not to
be confused with those in Chapter 1) let you deal, in a uniform manner,
with communications among various sources of data, such as files, network
connections, or memory blocks. We include detailed coverage of the reader
and writer classes that make it easy to deal with Unicode. We show you
what goes on under the hood when you use the object serialization
mechanism, which makes saving and loading objects easy and convenient.
We then move on to regular expressions and working with files and paths.
Throughout this chapter, you will find welcome enhancements in recent
Java versions.
Chapter 3 covers XML. We show you how to parse XML files, how to
generate XML, and how to use XSL transformations. As a useful example,
we show you how to specify the layout of a Swing form in XML. We also
discuss the XPath API, which makes finding needles in XML haystacks
much easier.
Chapter 4 covers the networking API. Java makes it phenomenally easy to
do complex network programming. We show you how to make network
connections to servers, how to implement your own servers, and how to
make HTTP connections. This chapter includes coverage of the new HTTP
client.
Chapter 5 covers database programming. The focus is on JDBC, the Java
database connectivity API that lets Java programs connect to relational
databases. We show you how to write useful programs to handle realistic
21. database chores, using a core subset of the JDBC API. (A complete
treatment of the JDBC API would require a book almost as big as this one.)
Java had two prior attempts at libraries for handling date and time. The
third one was the charm in Java 8. In Chapter 6, you will learn how to deal
with the complexities of calendars and time zones, using the new date and
time library.
Chapter 7 discusses a feature that we believe can only grow in importance:
internationalization. The Java programming language is one of the few
languages designed from the start to handle Unicode, but the
internationalization support on the Java platform goes much further. As a
result, you can internationalize Java applications so that they cross not only
platforms but country boundaries as well. For example, we show you how
to write a retirement calculator that uses either English, German, or Chinese
languages.
Chapter 8 discusses three techniques for processing code. The scripting
and compiler APIs allow your program to call code in scripting languages
such as JavaScript or Groovy, and to compile Java code. Annotations allow
you to add arbitrary information (sometimes called metadata) to a Java
program. We show you how annotation processors can harvest these
annotations at the source or class file level, and how annotations can be
used to influence the behavior of classes at runtime. Annotations are only
useful with tools, and we hope that our discussion will help you select
useful annotation processing tools for your needs.
In Chapter 9, you will learn about the Java Platform Module System that
was introduced in Java 9 to facilitate an orderly evolution of the Java
platform and core libraries. This module system provides encapsulation for
packages and a mechanism for describing module requirements. You will
learn the properties of modules so that you can decide whether to use them
in your own applications. Even if you decide not to, you need to know the
new rules so that you can interact with the Java platform and other
modularized libraries.
Chapter 10 takes up the Java security model, user authentication, and the
cryptographic functions in the Java security library. You will learn about
22. important features as message and code signing, authorization and
authentication, and encryption. We conclude with examples that use the
AES and RSA encryption algorithms.
Chapter 11 contains all the Swing material that didn’t make it into Volume
I, especially the important but complex tree and table components. We also
cover the Java 2D API, which you can use to create realistic drawings and
special effects. Of course, not many programmers need to program Swing
user interfaces these days, so we pay particular attention to features that are
useful for images that can be generated on a server.
Chapter 12 takes up native methods, which let you call methods written for
a specific machine such as the Microsoft Windows API. Obviously, this
feature is controversial: Use native methods, and the cross-platform nature
of Java vanishes. Nonetheless, every serious programmer writing Java
applications for specific platforms needs to know these techniques. At
times, you need to turn to the operating system’s API for your target
platform when you interact with a device or service that is not supported by
Java. We illustrate this by showing you how to access the registry API in
Windows from a Java program.
As always, all chapters have been completely revised for the latest version
of Java. Outdated material has been removed, and the new APIs up to Java
17 are covered in detail.
Conventions
As is common in many computer books, we use monospace type to
represent computer code.
Note
Notes are tagged with “note” icons that look like this.
23. Tip
Tips are tagged with “tip” icons that look like this.
Caution
When there is danger ahead, we warn you with a “caution” icon.
C++ Note:
There are a number of C++ notes that explain the difference between the
Java programming language and C++. You can skip them if you aren’t
interested in C++.
Java comes with a large programming library, or Application Programming
Interface (API). When using an API call for the first time, we add a short
summary description at the end of the section. These descriptions are a bit
more informal but, we hope, also a little more informative than those in the
official online API documentation. The names of interfaces are in italics,
just like in the official documentation. The number after a class, interface,
or method name is the JDK version in which the feature was introduced.
Application Programming Interface 1.2
Programs whose source code is included in the companion code for this
book are listed as examples, for instance
Listing 1.1 ScriptTest.java
24. You can download the companion code from
http://horstmann.com/corejava.
Register your copy of Core Java, Volume II—Advanced Features,
Eleventh Edition, on the InformIT site for convenient access to
updates and/or corrections as they become available. To start the
registration process, go to informit.com/register and log in
or create an account. Enter the product ISBN (9780135166314) and
click Submit. Look on the Registered Products tab for an Access
Bonus Content link next to this product, and follow that link to access
any available bonus materials. If you would like to be notified of
exclusive offers on new editions and updates, please check the box to
receive email from us.
25. Acknowledgments
Writing a book is always a monumental effort, and rewriting doesn’t seem
to be much easier, especially with such a rapid rate of change in Java
technology. Making a book a reality takes many dedicated people, and it is
my great pleasure to acknowledge the contributions of the entire Core Java
team.
A large number of individuals at Pearson provided valuable assistance, but
they managed to stay behind the scenes. I’d like them all to know how
much I appreciate their efforts. As always, my warm thanks go to my editor,
Greg Doench, for steering the book through the writing and production
process, and for allowing me to be blissfully unaware of the existence of all
those folks behind the scenes. I am very grateful to Julie Nahil for
production support, and to Dmitry Kirsanov and Alina Kirsanova for
copyediting and typesetting the manuscript.
Thanks to the many readers of earlier editions who reported embarrassing
errors and made lots of thoughtful suggestions for improvement. I am
particularly grateful to the excellent reviewing team that went over the
manuscript with an amazing eye for detail and saved me from many more
embarrassing errors.
Reviewers of this and earlier editions include Chuck Allison (Utah Valley
University), Lance Andersen (Oracle), Gail Anderson (Anderson Software
Group), Paul Anderson (Anderson Software Group), Alec Beaton (IBM),
Cliff Berg, Andrew Binstock (Oracle), Joshua Bloch, David Brown, Corky
26. Cartwright, Frank Cohen (PushToTest), Chris Crane (devXsolution), Dr.
Nicholas J. De Lillo (Manhattan College), Rakesh Dhoopar (Oracle),
Robert Evans (Senior Staff, The Johns Hopkins University Applied Physics
Lab), David Geary (Clarity Training), Jim Gish (Oracle), Brian Goetz
(Oracle), Angela Gordon, Dan Gordon (Electric Cloud), Rob Gordon, John
Gray (University of Hartford), Cameron Gregory (olabs.com), Steve
Haines, Marty Hall (coreservlets.com, Inc.), Vincent Hardy (Adobe
Systems), Dan Harkey (San Jose State University), William Higgins (IBM),
Marc Hoffmann (mtrail), Vladimir Ivanovic (PointBase), Jerry Jackson (CA
Technologies), Heinz Kabutz (Java Specialists), Stepan V. Kalinin (I-
Teco/Servionica LTD), Tim Kimmet (Walmart), Chris Laffra, Charlie Lai
(Apple), Angelika Langer, Jeff Langr (Langr Software Solutions), Doug
Langston, Hang Lau (McGill University), Mark Lawrence, Doug Lea
(SUNY Oswego), Gregory Longshore, Bob Lynch (Lynch Associates),
Philip Milne (consultant), Mark Morrissey (The Oregon Graduate Institute),
Mahesh Neelakanta (Florida Atlantic University), José Paumard (Oracle),
Hao Pham, Paul Philion, Blake Ragsdell, Ylber Ramadani (Ryerson
University), Stuart Reges (University of Arizona), Simon Ritter (Azul
Systems), Rich Rosen (Interactive Data Corporation), Peter Sanders (ESSI
University, Nice, France), Dr. Paul Sanghera (San Jose State University and
Brooks College), Paul Sevinc (Teamup AG), Devang Shah (Sun
Microsystems), Yoshiki Shibata, Richard Slywczak (NASA/Glenn Research
Center), Bradley A. Smith, Steven Stelting (Oracle), Christopher Taylor,
Luke Taylor (Valtech), George Thiruvathukal, Kim Topley
(StreamingEdge), Janet Traub, Paul Tyma (consultant), Christian
Ullenboom, Peter van der Linden, Burt Walsh, Joe Wang (Oracle), Dan Xu
(Oracle), and John Zavgren (Oracle).
Cay Horstmann
Berlin, Germany
December 2021
27. Chapter 1: Streams
In this chapter
• 1.1 From Iterating to Stream Operations
• 1.2 Stream Creation
• 1.3 The filter, map, and flatMap Methods
• 1.4 Extracting Substreams and Combining Streams
• 1.5 Other Stream Transformations
• 1.6 Simple Reductions
• 1.7 The Optional Type
• 1.8 Collecting Results
• 1.9 Collecting into Maps
• 1.10 Grouping and Partitioning
• 1.11 Downstream Collectors
• 1.12 Reduction Operations
• 1.13 Primitive Type Streams
• 1.14 Parallel Streams
Compared to collections, streams provide a view of data that lets you
specify computations at a higher conceptual level. With a stream, you
28. specify what you want to have done, not how to do it. You leave the
scheduling of operations to the implementation. For example, suppose you
want to compute the average of a certain property. You specify the source of
data and the property, and the stream library can then optimize the
computation, for example by using multiple threads for computing sums
and counts and combining the results.
In this chapter, you will learn how to use the Java stream library, which was
introduced in Java 8, to process collections in a “what, not how” style.
1.1 From Iterating to Stream
Operations
When you process a collection, you usually iterate over its elements and do
some work with each of them. For example, suppose we want to count all
long words in a book. First, let’s put them into a list:
var contents = Files.readString(Path.of("alice.txt"))); // Read
file into string
List<String> words = List.of(contents.split("PL+"));
// Split into words; nonletters are delimiters
Now we are ready to iterate:
int count = 0;
for (String w : words)
{
if (w.length() > 12) count++;
}
With streams, the same operation looks like this:
29. long count = words.stream()
.filter(w -> w.length() > 12)
.count();
Now you don’t have to scan the loop for evidence of filtering and counting.
The method names tell you right away what the code intends to do.
Moreover, where the loop prescribes the order of operations in complete
detail, a stream is able to schedule the operations any way it wants, as long
as the result is correct.
Simply changing stream to parallelStream allows the stream library
to do the filtering and counting in parallel.
long count = words.parallelStream()
.filter(w -> w.length() > 12)
.count();
Streams follow the “what, not how” principle. In our stream example, we
describe what needs to be done: get the long words and count them. We
don’t specify in which order, or in which thread, this should happen. In
contrast, the loop at the beginning of this section specifies exactly how the
computation should work, and thereby forgoes any chances of optimization.
A stream seems superficially similar to a collection, allowing you to
transform and retrieve data. But there are significant differences:
1. A stream does not store its elements. They may be stored in an
underlying collection or generated on demand.
2. Stream operations don’t mutate their source. For example, the filter
method does not remove elements from a stream but yields a new stream
in which they are not present.
3. Stream operations are lazy when possible. This means they are not
executed until their result is needed. For example, if you only ask for the
first five long words instead of all, the filter method will stop filtering
after the fifth match. As a consequence, you can even have infinite
streams!
30. Let us have another look at the example. The stream and
parallelStream methods yield a stream for the words list. The
filter method returns another stream that contains only the words of
length greater than twelve. The count method reduces that stream to a
result.
This workflow is typical when you work with streams. You set up a pipeline
of operations in three stages:
1. Create a stream.
2. Specify intermediate operations for transforming the initial stream into
others, possibly in multiple steps.
3. Apply a terminal operation to produce a result. This operation forces the
execution of the lazy operations that precede it. Afterwards, the stream
can no longer be used.
In the example in Listing 1.1, the stream is created with the stream or
parallelStream method. The filter method transforms it, and
count is the terminal operation.
In the next section, you will see how to create a stream. The subsequent
three sections deal with stream transformations. They are followed by five
sections on terminal operations.
Listing 1.1 streams/CountLongWords.java
1 package streams;
2
3 import java.io.*;
4 import java.nio.file.*;
5 import java.util.*;
6
7 /**
8 * @version 1.02 2019-08-28
9 * @author Cay Horstmann
10 */
31. 11 public class CountLongWords
12 {
13 public static void main(String[] args) throws IOException
14 {
15 var contents = Files.readString(
16 Path.of("../gutenberg/alice30.txt"));
17 List<String> words = List.of(contents.split("PL+"));
18
19 long count = 0;
20 for (String w : words)
21 {
22 if (w.length() > 12) count++;
23 }
24 System.out.println(count);
25
26 count = words.stream().filter(w -> w.length() >
12).count();
27 System.out.println(count);
28
29 count = words.parallelStream().filter(w -> w.length() >
12).count();
30 System.out.println(count);
31 }
32 }
java.util.stream.Stream<T> 8
• Stream<T> filter(Predicate<? super T> p)
yields a stream containing all elements of this stream fulfilling p.
• long count()
yields the number of elements of this stream. This is a terminal
operation.
java.util.Collection<E> 1.2
32. • default Stream<E> stream()
• default Stream<E> parallelStream()
yield a sequential or parallel stream of the elements in this
collection.
1.2 Stream Creation
You have already seen that you can turn any collection into a stream with
the stream method of the Collection interface. If you have an array,
use the static Stream.of method instead.
Stream<String> words = Stream.of(contents.split("PL+"));
// split returns a String[] array
The of method has a varargs parameter, so you can construct a stream from
any number of arguments:
Stream<String> song = Stream.of("gently", "down", "the",
"stream");
Use Arrays.stream(array, from, to) to make a stream from a
part of an array.
To make a stream with no elements, use the static Stream.empty
method:
Stream<String> silence = Stream.empty();
// Generic type <String> is inferred; same as Stream.
<String>empty()
33. The Stream interface has two static methods for making infinite streams.
The generate method takes a function with no arguments (or,
technically, an object of the Supplier<T> interface). Whenever a stream
value is needed, that function is called to produce a value. You can get a
stream of constant values as
Stream<String> echos = Stream.generate(() -> "Echo");
or a stream of random numbers as
Stream<Double> randoms = Stream.generate(Math::random);
To produce sequences such as 0 1 2 3 . . ., use the iterate
method instead. It takes a “seed” value and a function (technically, a
UnaryOperator<T>) and repeatedly applies the function to the previous
result. For example,
Stream<BigInteger> integers
= Stream.iterate(BigInteger.ZERO, n -> n.add(BigInteger.ONE));
The first element in the sequence is the seed BigInteger.ZERO. The
second element is f(seed) which yields 1 (as a big integer). The next
element is f(f(seed)) which yields 2, and so on.
To produce a finite stream instead, add a predicate that specifies when the
iteration should finish:
var limit = new BigInteger("10000000");
Stream<BigInteger> integers
= Stream.iterate(BigInteger.ZERO,
n -> n.compareTo(limit) < 0,
n -> n.add(BigInteger.ONE));
As soon as the predicate rejects an iteratively generated value, the stream
ends.
34. Finally, the Stream.ofNullable method makes a really short stream
from an object. The stream has length 0 if the object is null or length 1
otherwise, containing just the object. This is mostly useful in conjunction
with flatMap—see Section 1.7.7, “Turning an Optional into a Stream,”
on p. 23 for an example.
Note
A number of methods in the Java API yield streams. For example, the
String class has a lines method that yields a stream of the lines
contained in the string:
Stream<String> greetings = "HellonGuten TagnBonjour".lines()
The Pattern class has a method splitAsStream that splits a
CharSequence by a regular expression. You can use the following
statement to split a string into words:
Stream<String> words =
Pattern.compile("PL+").splitAsStream(contents);
The Scanner.tokens method yields a stream of tokens of a scanner.
Another way to get a stream of words from a string is
Stream<String> words = new Scanner(contents).tokens();
The static Files.lines method returns a Stream of all lines in a
file:
try (Stream<String> lines = Files.lines(path)) {
Process lines
}
To view the contents of one of the streams introduced in this section, use
the toList method, which collects the stream’s elements in a list. Like
count, toList is a terminal operation. If the stream is infinite, first
truncate it with the limit method:
35. System.out.println(Stream.generate(Math::random)
.limit(10).toList());
Note
If you have an Iterable that is not a collection, you can turn it into a
stream by calling
StreamSupport.stream(iterable.spliterator(), false);
If you have an Iterator and want a stream of its results, use
StreamSupport.stream(Spliterators.spliteratorUnknownSize(
iterator, Spliterator.ORDERED), false);
Caution
It is very important that you don’t modify the collection backing a
stream while carrying out a stream operation. Remember that streams
don’t collect their data—the data is always in a separate collection. If
you modify that collection, the outcome of the stream operations
becomes undefined. The JDK documentation refers to this requirement
as noninterference.
To be exact, since intermediate stream operations are lazy, it is possible
to mutate the collection up to the point where the terminal operation
executes. For example, the following, while certainly not recommended,
will work:
List<String> wordList = . . .;
Stream<String> words = wordList.stream();
wordList.add("END");
long n = words.distinct().count();
But this code is wrong:
36. Stream<String> words = wordList.stream();
words.forEach(s -> {if (s.length() < 12) wordList.remove(s);});
// ERROR--interference
The example program in Listing 1.2 shows the various ways of creating a
stream.
Listing 1.2 streams/CreatingStreams.java
1 package streams;
2
3 import java.io.*;
4 import java.math.*;
5 import java.nio.file.*;
6 import java.util.*;
7 import java.util.regex.Pattern;
8 import java.util.stream.*;
9
10 /**
11 * @version 1.03 2021-09-06
12 * @author Cay Horstmann
13 */
14 public class CreatingStreams
15 {
16 public static <T> void show(String title, Stream<T>
stream)
17 {
18 final int SIZE = 10;
19 List<T> firstElements = stream
20 .limit(SIZE + 1)
21 .toList();
22 System.out.print(title + ": ");
23 for (int i = 0; i < firstElements.size(); i++)
24 {
25 if (i > 0) System.out.print(", ");
26 if (i < SIZE)
38. 60 try (Stream<String> lines = Files.lines(path))
61 {
62 show("lines", lines);
63 }
64
65 Iterable<Path> iterable =
FileSystems.getDefault().getRootDirectories();
66 Stream<Path> rootDirectories =
StreamSupport.stream(iterable.spliterator(), false);
67 show("rootDirectories", rootDirectories);
68
69 Iterator<Path> iterator =
Path.of("/usr/share/dict/words").iterator();
70 Stream<Path> pathComponents =
StreamSupport.stream(Spliterators.spliteratorUnknownSize(
71 iterator, Spliterator.ORDERED), false);
72 show("pathComponents", pathComponents);
73 }
74 }
java.util.stream.Stream 8
• static <T> Stream<T> of(T... values)
yields a stream whose elements are the given values.
• static <T> Stream<T> empty()
yields a stream with no elements.
• static <T> Stream<T> generate(Supplier<T> s)
yields an infinite stream whose elements are constructed by
repeatedly invoking the function s.
• static <T> Stream<T> iterate(T seed,
UnaryOperator<T> f)
• static <T> Stream<T> iterate(T seed,
Predicate<? super T> hasNext, UnaryOperator<T>
f)
39. yield a stream whose elements are seed, f invoked on seed, f invoked
on the preceding element, and so on. The first method yields an
infinite stream. The stream of the second method comes to an end
before the first element that doesn’t fulfill the hasNext predicate.
• static <T> Stream<T> ofNullable(T t) 9
returns an empty stream if t is null or a stream containing t
otherwise.
java.util.Spliterators 8
• static <T> Spliterator<T>
spliteratorUnknownSize(Iterator<? extends T>
iterator, int characteristics)
turns an iterator into a splittable iterator of unknown size with the
given characteristics (a bit pattern containing constants such as
Spliterator.ORDERED).
java.util.Arrays 1.2
• static <T> Stream<T> stream(T[] array, int
startInclusive, int endExclusive) 8
yields a stream whose elements are the specified range of the array.
java.lang.String
• static Stream<String> lines() 11
yields a stream whose elements are the lines of this string.
40. java.util.regex.Pattern 1.4
• Stream<String> splitAsStream(CharSequence input) 8
yields a stream whose elements are the parts of the input that are
delimited by this pattern.
java.nio.file.Files 7
• static Stream<String> lines(Path path) 8
• static Stream<String> lines(Path path, Charset
cs) 8
yield a stream whose elements are the lines of the specified file, with
the UTF-8 charset or the given charset.
java.util.stream.StreamSupport 8
• static <T> Stream<T> stream(Spliterator<T>
spliterator, boolean parallel)
yields a stream containing the values produced by the given
splittable iterator.
java.lang.Iterable 5
• Spliterator<T> spliterator() 8
yields a splittable iterator for this Iterable. The default
implementation does not split and does not report a size.
41. java.util.Scanner 5
• public Stream<String> tokens() 9
yields a stream of strings returned by calling the next method of this
scanner.
java.util.function.Supplier<T> 8
• T get()
supplies a value.
1.3 The filter, map, and flatMap
Methods
A stream transformation produces a stream whose elements are derived
from those of another stream. You have already seen the filter
transformation that yields a new stream with those elements that match a
certain condition. Here, we transform a stream of strings into another
stream containing only long words:
List<String> words = . . .;
Stream<String> longWords = words.stream().filter(w -> w.length()
> 12);
The argument of filter is a Predicate<T>—that is, a function from T to
boolean.
42. Often, you want to transform the values in a stream in some way. Use the
map method and pass the function that carries out the transformation. For
example, you can transform all words to lowercase like this:
Stream<String> lowercaseWords =
words.stream().map(String::toLowerCase);
Here, we used map with a method reference. Often, you will use a lambda
expression instead:
Stream<String> firstLetters = words.stream().map(s ->
s.substring(0, 1));
The resulting stream contains the first letter of each word.
When you use map, a function is applied to each element, and the result is a
new stream with the results. Occasionally, you are faced with a mapping
function that generates an optional result, or more than one result. As an
example, consider a method codePoints that yields all code points of a
string. For example, codePoints("Hello ") would consist of "H",
"e", "l", "l", "o", " ", " ". Note that the globe symbol (U+1F310)
consists of two char values, so the codePoints method has to do some
heavy lifting to make this happen. We will look at a couple of
implementations momentarily.
How should codePoints collect its multiple results? For the stream API,
it is most natural if the method returns a Stream<String>.
Now let’s map such a codePoints method on a stream of strings:
Stream<Stream<String>> result = words.stream().map(w ->
codePoints(w));
You will get a stream of streams, like [. . . ["y", "o", "u",
"r"], ["b", "o", "a", "t"], . . .]. To flatten it out to a
43. single stream [. . . "y", "o", "u", "r", "b", "o", "a",
"t", . . .], use the flatMap method instead of map:
Stream<String> flatResult = words.stream().flatMap(w ->
codePoints(w));
// Calls codePoints on each word and flattens the results
Now that you have seen how to use the codePoints method, how do you
write it? The String class has a codePoints method that yields a
stream of integer code points:
"Hello ".codePoints() // A stream of integers 72, 101, 108, 108,
111, 32, 127760
Next, we need to transform each of the integers to a string containing the
Unicode character with the given code point. Unfortunately, there is a
technical difficulty. The codePoints method produces an IntStream,
which is a little different from a Stream<Integer>, as you will see in
Section 1.13, “Primitive Type Streams,” on p. 43. Instead of map, you use
the mapToObj method to transform the elements. Perhaps surprisingly,
there is no convenient method for turning an integer codepoint into a string.
Here is the best I could come up with:
public static Stream<String> codePoints(String s)
{
return s.codePoints().mapToObj(cp -> new String(new int [] {
cp }, 0, 1));
}
When using flatMap, you provide a method that produces a new stream
for every stream element. As you have seen, that can be tedious. It can also
be a little inefficient. The mapMulti method offers an alternative. Instead
of producing a stream of results, you generate the results and pass them to a
collector—an object of a class implementing the functional interface
Consumer. For each result, invoke the collector’s accept method.
44. Let’s do this with an example. The following loop produces the code points
of a string s:
int i = 0;
while (i < s.length())
{
int cp = sentence.codePointAt(i);
// Do something with cp
if (Character.isSupplementaryCodePoint(cp)) i += 2;
else i++;
}
When calling mapMulti, you provide a function that is invoked with the
stream element and the collector. In your function, pass your results to the
collector.
Stream<String> result = words.stream().mapMulti((s, collector) ->
{
int i = 0;
while (i < s.length())
{
int cp = sentence.codePointAt(i);
collector.accept(cp);
if (Character.isSupplementaryCodePoint(cp)) i += 2;
else i++;
}
});
java.util.stream.Stream 8
• Stream<T> filter(Predicate<? super T>
predicate)
yields a stream containing the elements of this stream that fulfill the
predicate.
45. • <R> Stream<R> map(Function<? super T,? extends
R> mapper)
yields a stream containing the results of applying mapper to the
elements of this stream.
• <R> Stream<R> flatMap(Function<? super T,?
extends Stream<? extends R>> mapper)
yields a stream obtained by concatenating the results of applying
mapper to the elements of this stream. (Note that each mapper
result is a stream.)
• <R> Stream<R> mapMulti(BiConsumer<? super T,?
super Consumer<R>> mapper) 16
For each stream element, the mapper is invoked , and all elements
passed to the Consumer during invocation are added to the result
stream.
1.4 Extracting Substreams and
Combining Streams
The call stream.limit(n) returns a new stream that ends after n
elements (or when the original stream ends if it is shorter). This method is
particularly useful for cutting infinite streams down to size. For example,
Stream<Double> randoms =
Stream.generate(Math::random).limit(100);
yields a stream with 100 random numbers.
The call stream.skip(n) does the exact opposite. It discards the first n
elements. This is handy in our book reading example where, due to the way
the split method works, the first element is an unwanted empty string.
We can make it go away by calling skip:
46. Stream<String> words =
Stream.of(contents.split("PL+")).skip(1);
The stream.takeWhile(predicate) call takes all elements from the
stream while the predicate is true, and then stops.
For example, suppose we use the codePoints method of the preceding
section to split a string into characters, and we want to collect all initial
digits. The takeWhile method can do this:
Stream<String> initialDigits = codePoints(str).takeWhile(
s -> "0123456789".contains(s));
The dropWhile method does the opposite, dropping elements while a
condition is true and yielding a stream of all elements starting with the first
one for which the condition was false. For example,
Stream<String> withoutInitialWhiteSpace =
codePoints(str).dropWhile(
s -> s.strip().length() == 0);
You can concatenate two streams with the static concat method of the
Stream class:
Stream<String> combined = Stream.concat(
codePoints("Hello"), codePoints("World"));
// Yields the stream ["H", "e", "l", "l", "o", "W", "o", "r",
"l", "d"]
Of course, the first stream should not be infinite—otherwise the second one
wouldn’t ever get a chance.
java.util.stream.Stream 8
47. • Stream<T> limit(long maxSize)
yields a stream with up to maxSize of the initial elements from this
stream.
• Stream<T> skip(long n)
yields a stream whose elements are all but the initial n elements of
this stream.
• Stream<T> takeWhile(Predicate<? super T>
predicate) 9
yields a stream whose elements are the initial elements of this stream
that fulfill the predicate.
• Stream<T> dropWhile(Predicate<? super T>
predicate) 9
yields a stream whose elements are the elements of this stream
except for the initial ones that do not fulfill the predicate.
• static <T> Stream<T> concat(Stream<? extends
T> a, Stream<? extends T> b)
yields a stream whose elements are the elements of a followed by
the elements of b.
1.5 Other Stream Transformations
The distinct method returns a stream that yields elements from the
original stream, in the same order, except that duplicates are suppressed.
The duplicates need not be adjacent.
Stream<String> uniqueWords
= Stream.of("merrily", "merrily", "merrily",
"gently").distinct();
// Only one "merrily" is retained
48. For sorting a stream, there are several variations of the sorted method.
One works for streams of Comparable elements, and another accepts a
Comparator. Here, we sort strings so that the longest ones come first:
Stream<String> longestFirst
=
words.stream().sorted(Comparator.comparing(String::length).revers
ed());
As with all stream transformations, the sorted method yields a new
stream whose elements are the elements of the original stream in sorted
order.
Of course, you can sort a collection without using streams. The sorted
method is useful when the sorting process is part of a stream pipeline.
Finally, the peek method yields another stream with the same elements as
the original, but a function is invoked every time an element is retrieved.
That is handy for debugging:
Object[] powers = Stream.iterate(1.0, p -> p * 2)
.peek(e -> System.out.println("Fetching " + e))
.limit(20).toArray();
When an element is actually accessed, a message is printed. This way you
can verify that the infinite stream returned by iterate is processed lazily.
Tip
When you use a debugger to debug a stream computation, you can set a
breakpoint in a method that is called from one of the transformations.
With most IDEs, you can also set breakpoints in lambda expressions. If
you just want to know what happens at a particular point in the stream
pipeline, add
49. .peek(x -> {
return; })
and set a breakpoint on the second line.
java.util.stream.Stream 8
• Stream<T> distinct()
yields a stream of the distinct elements of this stream.
• Stream<T> sorted()
• Stream<T> sorted(Comparator<? super T>
comparator)
yield a stream whose elements are the elements of this stream in
sorted order. The first method requires that the elements are
instances of a class implementing Comparable.
• Stream<T> peek(Consumer<? super T> action)
yields a stream with the same elements as this stream, passing each
element to action as it is consumed.
1.6 Simple Reductions
Now that you have seen how to create and transform streams, we will
finally get to the most important point—getting answers from the stream
data. The methods covered in this section are called reductions. Reductions
are terminal operations. They reduce the stream to a nonstream value that
can be used in your program.
You have already seen a simple reduction: the count method that returns
the number of elements of a stream.
50. Other simple reductions are max and min that return the largest or smallest
value. There is a twist—these methods return an Optional<T> value that
either wraps the answer or indicates that there is none (because the stream
happened to be empty). In the olden days, it was common to return null in
such a situation. But that can lead to null pointer exceptions when it
happens in an incompletely tested program. The Optional type is a better
way of indicating a missing return value. We discuss the Optional type
in detail in the next section. Here is how you can get the maximum of a
stream:
Optional<String> largest =
words.max(String::compareToIgnoreCase);
System.out.println("largest: " + largest.orElse(""));
The findFirst returns the first value in a nonempty collection. It is often
useful when combined with filter. For example, here we find the first
word that starts with the letter Q, if it exists:
Optional<String> startsWithQ
= words.filter(s -> s.startsWith("Q")).findFirst();
If you are OK with any match, not just the first one, use the findAny
method. This is effective when you parallelize the stream, since the stream
can report any match that it finds instead of being constrained to the first
one.
Optional<String> startsWithQ
= words.parallel().filter(s -> s.startsWith("Q")).findAny();
If you just want to know if there is a match, use anyMatch. That method
takes a predicate argument, so you won’t need to use filter.
boolean aWordStartsWithQ
= words.parallel().anyMatch(s -> s.startsWith("Q"));
51. There are methods allMatch and noneMatch that return true if all or
no elements match a predicate. These methods also benefit from being run
in parallel.
java.util.stream.Stream 8
• Optional<T> max(Comparator<? super T>
comparator)
• Optional<T> min(Comparator<? super T>
comparator)
yield a maximum or minimum element of this stream, using the
ordering defined by the given comparator, or an empty Optional
if this stream is empty. These are terminal operations.
• Optional<T> findFirst()
• Optional<T> findAny()
yield the first, or any, element of this stream, or an empty
Optional if this stream is empty. These are terminal operations.
• boolean anyMatch(Predicate<? super T>
predicate)
• boolean allMatch(Predicate<? super T>
predicate)
• boolean noneMatch(Predicate<? super T>
predicate)
return true if any, all, or none of the elements of this stream match
the given predicate. These are terminal operations.
1.7 The Optional Type
An Optional<T> object is a wrapper for either an object of type T or no
object. In the former case, we say that the value is present. The
52. Optional<T> type is intended as a safer alternative for a reference of
type T that either refers to an object or is null. But it is only safer if you
use it right. The next three sections shows you how.
1.7.1 Getting an Optional Value
The key to using Optional effectively is to use a method that either
produces an alternative if the value is not present, or consumes the value
only if it is present.
In this section, we look at the first strategy. Often, there is a default that you
want to use when there was no match, perhaps the empty string:
String result = optionalString.orElse("");
// The wrapped string, or "" if none
You can also invoke code to compute the default:
String result = optionalString.orElseGet(() ->
System.getProperty("myapp.default"));
// The function is only called when needed
Or you can throw an exception if there is no value:
String result =
optionalString.orElseThrow(IllegalStateException::new);
// Supply a method that yields an exception object
java.util.Optional 8
• T orElse(T other)
yields the value of this Optional, or other if this Optional is
empty.
• T orElseGet(Supplier<? extends T> other)
53. yields the value of this Optional, or the result of invoking other
if this Optional is empty.
• <X extends Throwable> T orElseThrow(Supplier<?
extends X> exceptionSupplier)
yields the value of this Optional, or throws the result of invoking
exceptionSupplier if this Optional is empty.
1.7.2 Consuming an Optional Value
In the preceding section, you saw how to produce an alternative if no value
is present. The other strategy for working with optional values is to
consume the value only if it is present.
The ifPresent method accepts a function. If the optional value exists, it
is passed to that function. Otherwise, nothing happens.
optionalValue.ifPresent(v -> Process v);
For example, if you want to add the value to a set if it is present, call
optionalValue.ifPresent(v -> results.add(v));
or simply
optionalValue.ifPresent(results::add);
If you want to take one action if the Optional has a value and another
action if it doesn’t, use ifPresentOrElse:
optionalValue.ifPresentOrElse(
v -> System.out.println("Found " + v),
() -> logger.warning("No match"));
54. java.util.Optional 8
• void ifPresent(Consumer<? super T> action)
If this Optional is nonempty, passes its value to action.
• void ifPresentOrElse(Consumer<? super T>
action, Runnable emptyAction) 9
If this Optional is nonempty, passes its value to action, else
invokes emptyAction.
1.7.3 Pipelining Optional Values
In the preceding sections, you saw how to get a value out of an Optional
object. Another useful strategy is to keep the Optional intact. You can
transform the value inside an Optional by using the map method:
Optional<String> transformed =
optionalString.map(String::toUpperCase);
If optionalString is empty, then transformed is also empty.
Here is another example. We add a result to a list if it is present:
optionalValue.map(results::add);
If optionalValue is empty, nothing happens.
Note
This map method is the analog of the map method of the Stream
interface that you have seen in Section 1.3, “The filter, map, and
flatMap Methods,” on p. 11. Simply imagine an optional value as a
56. "Do you know that lady!" I heard them ask.
"Yes, and the nigger too. It's Miss Salome Poillon, and she lives at S
—— plantation, across the river," was the answer.
"Then she is a resident here, and there is no danger of their being
spies?" put in the cautious one.
"Lord, no! Why, she's the biggest Rebel 'round. So's all the family,
an' she's got a Rebel lover," replied my champion emphatically,
adding the last fact as if it were a clincher.
That settled it, and the two officers then came over to the carriage
and told me I was at liberty to go on, and regretted that they had
been obliged to stop me at all. I thanked them, and asked if I would
have much difficulty in getting through.
"I am afraid so," replied the one who had first met me.
"This is your most direct route, is it not?" asked the older officer, on
whom the rest of the conversation devolved.
"It is much the nearest way," I replied.
"It leads directly on, near where a considerable body of our troops
are, yet I think it will be safer for you to keep it than to try side
roads, where you would be constantly stopped. I will give you a note
to the general in command, and a pass, which will aid you until you
reach him. He will likely give you an escort for some distance," he
added, writing as he spoke.
When he handed me the papers, I asked him about the positions of
the Yankees, and in answering he told me also something new about
how Luce's army was located, which was one of the clues that I
wanted to learn.
I had no idea of using the papers unless I should fail in all efforts to
find Captain DeLacy. I told Ned not to refer to them in any way or to
our encounter, while he should be separated from me, and
57. impressed on him that he was not to get out of the buggy if he
could help it, or leave the horses one moment unless dragged away
by force. I regretted that we had run into the camp, for it took
valuable time, and it did not make me feel any better about it to
know that it had happened through my own carelessness. If I had
been watching out, as I ought to have been, I would have noticed
the fires in time to have avoided them by making a detour, and I
believed that I could have gotten later the valuable bit of information
the talkative officer had given me.
58. CHAPTER XI.
The encounter had one good result, however. It got us over our
stage fright, as it were, and rather raised us up to the grand climax.
We had driven nearly three miles farther before we ran into the
Rebel camp again. When we finally found ourselves making our way
under guard to General Dare's headquarters, we were far more
composed than we could possibly have been had we not already had
some experience.
When stopped, I had insisted on being allowed to proceed, but as I
expected and desired, the simple privilege of following my own way
was denied me. My statements regarding my identity were received
with incredulity. I insisted on the truth of my story, and I demanded
that I be taken to headquarters at once. After some parley, my
request was acceded to and a couple of soldiers took their places at
the horses' heads and slowly led them forward, while a guard walked
at the side of the buggy until we reached a cluster of tents pitched
somewhat apart, in front of which stood four or five officers
conversing.
The officer who had brought us in advanced to the group, and I
could hear him reporting the circumstances of our arrest. A
handsome subaltern came forward to assist me from the buggy, and
I was soon answering the curtly-put inquiries of the middle aged
officer to whom I had been conducted. I repeated my story. He
questioned and cross-questioned me severely, but I was too entirely
familiar with my ground to be caught tripping. I felt a good deal as if
I were an actor in a play, and while I must say that I did not
particularly admire the setting, I began to have an intense interest in
rendering my part well and having all go off smoothly.
59. Ned was seated in the buggy within hearing distance and I saw he
had assumed, or was really feeling, about the right amount of
anxiety, and that no one seemed to be paying any attention
whatever to him.
I did not recognize the officer interrogating me, but I heard him
addressed by one of the other officers as Colonel Sofield. When after
telling him my story, he utterly refused to credit it. I asked to see the
General in command. Col. Sofield replied that General Senhouse had
gone over to confer with General Leonard and might not be back
until morning, not for several hours certainly, and followed the
explanation with an intimation that both myself and my servant
would be well off under guard until his return.
I was somewhat nonplussed when the officer said General
Senhouse. I had looked on General Dare only as a guide to Captain
DeLacy, and had no interest whatever beyond that in him. At the
same time I was a trifle surprised that I had not been taken before
him, and that reference had not been made to him instead of to
General Senhouse. I began to wonder if it were possible that I had
not reached Dare's headquarters, but I did not dare ask directly or
betray more knowledge of army details than a girl would be likely to
know. After pondering a moment, I said:
"I ought perhaps to have stopped at A——, as I was advised to do,
but I was so very anxious to get on, that I could not make up my
mind to delay there. Will you tell me what regiment this is? I have
friends and relatives with General Luce and there may be some one
here who can identify me."
An orderly was presenting a paper to Col. Sofield as I finished
speaking, and another officer, who had come up but a short time
previous and was standing near, in company with the others,
answered:
"This is General Dare's division, but General Senhouse is in
command at present. Over on the left there is the —— Regiment,
60. —— Brigade; others are further on. If you will give the names of
your friends, and they are here, they can be sent for."
"Captain DeLacy is with General Dare. If I could see him, he would
assure you that I am just who I represent myself. He is a very
intimate friend of the family," I said, turning again to my first
interlocuter.
"Impossible," he replied, "Captain DeLacy has just started to inspect
a position several miles from here. There is no telling when he will
be back."
"Beg pardon, Colonel, but Captain DeLacy has not got off yet. He
passed us on the way over here, and I saw him go in Colonel
Lounsbery's tent a few minutes ago," spoke up another officer.
"There he comes now," he added, as a tall figure came out of a tent
near by.
Affairs progressed rapidly in the next few minutes. In less time than
I could write it, Captain DeLacy had been called over to identify me;
had done it, even to the satisfaction of the obdurate Colonel, and
beard the story of my detention, and my anxious request that I
might go on at once.
Captain DeLacy asked and received permission to take me into a
neighboring tent, where I could wait, freed from the gaze of those
who had gathered around to see what was going on, until he could
procure the passes necessary to insure my safe conduct through
their lines. Colonel Sofield, whose good manners had increased in
proportion to the strengthening of his convictions that I was not a
spy, told him to take me into General Dare's tent, as it was the
nearest one unoccupied, then to return to him for passes.
A moment later I was alone with the only man of them all who could
penetrate my disguise. His first words assured me that he had not
heard from Salome lately enough to imperil my statements. And his
hurried whispers of love and devotion, together with his grave
concern at my having undertaken a journey through that section at
61. so dangerous a time, proved that he accepted me in perfect good
faith.
Even at that desperate moment, at the touch of the Captain's lips I
was filled with an unholy glee.
Fortunately, he had little time to play the lover. Love and war are an
ill-matched couple, and except that both set at naught all interfering
laws, they have nothing in common. The latter never relaxes the
grasp of a master and exacts that all who serve him shall fulfill their
duty to the utmost, without delay or flinching, although by so doing
all pleasures, affections, ties of kindred and life itself are yielded up.
My expressed anxiety for his safety, and pretended impression that
he was on some dangerous raid, led Captain DeLacy to assure me
that he was with Luce, and to tell me what forces Luce had with
him, but no more about his future movements than I had already
gathered, which amounted to but little beyond a clue to the meaning
of General Middleworth's movement, which I had witnessed that
afternoon. I questioned as closely as I dared, but elicited nothing
further. My shrewdest efforts were a failure. I saw that he either had
not been informed of the object of the campaign, or felt bound not
to reveal it even to one whom he held as dear as he did Salome.
62. CHAPTER XII.
While conversing with Captain DeLacy, I had become as familiar with
the interior of the tent as I could by the light of one inferior candle
and the use of my eyes. There seemed nothing there to invite
investigation.
Even after Captain DeLacy had reluctantly left me, a closer
inspection revealed nothing more promising. I sat on a camp stool,
in a corner; near was a pile of blankets; a rough camp chair stood
between me and the bed; a bayonet stuck in the ground did duty for
a candlestick, and on an empty wooden box near me lay a paper-
covered book.
I had just had time to run a hasty glance through the book, when
the fly was raised and an officer entered. As was only natural, he
started when he saw me, then lifted his hat with a half-spoken
apology, tossed a newspaper carelessly on the bed, threw his
overcoat over the chair and went out again.
I recognized him instantly as General Dare. His actions and looks
struck me as those of a man who felt at odds with the world and
who was nursing a grievance, but I was too deeply concerned about
my own affairs to be more than casually impressed with what I
learned afterwards was the case.
It is a strange fact that in times of most intense suffering, deadly
peril and deepest thought, the eye will be attracted by the most
trivial objects. While I anxiously pondered my next move, my eye
mechanically followed in and out the fantastically curved line made
by the shadows cast by the pile of blankets, then by the edge of the
coat cape as it trailed along the floor. I had followed it almost to the
end when my gaze was arrested by a spot of color differing from the
rest. With a start, I realized that I was looking at a flat, long book. I
63. could not tell then and I cannot tell now whether it fell from the
overcoat or was lying there when I entered, but I do not see how it
could have been there at first and escaped my observation.
I determined at once to see the contents of that book. There was
not one instant to be lost. I well knew that even then some one
might be standing at the entrance and that the Captain would return
at any moment. But examine that book I must, even at the risk of
surprise, detection and death. It was the most critical moment I had
yet encountered. I had to think and act together.
Throwing myself at full length on the grassy floor, with my head
screened from the first glance of any one entering, intending to
feign a swoon if any one did come, I extended my arm above my
head, in the shelter of the chair, and had the book in my impatient
fingers.
Opening it hastily, I scanned it in the dim light which came over my
shoulder from the flickering candle. I was confronted by a series of
blank pages. General Dare's name was on the fly leaf. Only the first
three pages were written on, and they contained nothing except
detached items of interest to him only. Evidently, the book had been
newly purchased, for the dates ran but a few days back.
Bitterly disappointed, I ran over the pages again, and a folded paper
slipped into view. Even to this day I can distinctly feel the wild
bound of exultation my heart gave when I knew that I held in my
hands a copy of Special Order No. 000, issued by the Rebel
Commander in Chief only four days before, and regulating the
movements of all the divisions of his army for several days to come.
At the sight of that paper every drop of blood in my body seemed to
rush to my heart, only to leave it again with a wild speed that turned
me faint and dizzy. The letters danced before my eyes, but even in
that one hasty glance I took in enough to know that I need seek no
further information. I had succeeded even beyond my hopes and
expectations. If I could get safely back with that paper, and
64. whatever else I had learned, I felt check to the Rebels must be
insured.
Hastily concealing the paper, I pushed the book under the bed, and
had barely regained my place when Captain DeLacy re-entered with
the passes. There was no time for further private conversation
between us, which I regarded as a piece of good luck.
Captain DeLacy told me, while he hastily assorted the papers in his
hand, that he was obliged to proceed without delay on the important
duty for which he was preparing when Colonel Sofield had called him
to me; that as the first part of our way lay the same as his, he could
act as my escort until his road turned off from the one I was to
follow. From where he had to leave me, to H—— was only ten miles,
and he exacted a promise that I would remain there with friends
until morning.
I could not but be touched at his anxiety about me, impatient as I
was at the delay which it caused.
We started almost immediately. Captain DeLacy rode at the side of
the buggy and the squad of men with him a short distance in
advance. The road was clear, and we made excellent time.
At last the moment of separation came. His real farewell had already
been said, so before following his men down the dark path, into
which they had turned, the Captain paused only for some cautions
to Ned and a quickly spoken "good bye" to me, which held as much
as was ever put in that simple word.
I realized fully what the parting was to him. He had accepted me as
Salome, without doubt or question, and to leave me with no other
protector than Ned tried him sorely.
I leaned out of the buggy and looked back after him, with a feeling
of pain that surprised me. As he disappeared, a presentment that I
should never see him again crept over me, followed by an idle
speculation whether it was he or I who was first to meet our fate, a
65. feeling which I remembered well a few months later, when I
received the news that Captain DeLacy had been shot in battle.
66. CHAPTER XIII.
Shaking off the dim sense of foreboding, I gave my thoughts entirely
to the task before me. I had decided to make my way down the side
of the river I was then on. From what I had learned of the position
of the enemy, I knew the risk would be no greater than if I crossed
to the opposite shore, and I hoped to save many weary miles of
travel. Being well aware of the extreme caution shown on our side, I
thought the chances were that our army would be yet in the
neighborhood of the place where I left them, and I aimed for that
point.
I told Ned that I had secured a paper of the utmost importance, and
that if I were shot and he escaped, he was to take the paper from
its place of concealment and carry it on.
We turned to the left, down the first road we came to, after parting
with Captain DeLacy and his men. Just before we reached it, we
were stopped by a small party of Confederates on horseback. I
offered my passes. Striking a match, an officer read them, and after
a few questions, allowed us to go on. That was the only time the
passes were of use to us, for as soon as I parted with my disguise
they were, of course, worthless.
In order to make the best time possible, and avail ourselves of short
cuts and bridle paths, it was necessary to leave the buggy and
return to horseback. That we did at the earliest practical moment. As
soon as we came to a rough bit of road, after our first turn, Ned
drove the buggy to one side, and, knocking off a wheel, left it to its
fate. When I was again in my own clothes, we made the harness
and my disguise into several bundles, which Ned weighted and
dropped into the first creek we came to.
67. That done, we hurried on. The night had turned cloudy and dark
while we had been in the Confederate camp. It did not rain, but
before long we struck a place where it had very recently, and our
horses for a short distance were obliged to plough through slippery
clay. Frequently we would see the fires of some outpost, and often a
picket shot, sometimes startlingly near, would ring out on the murky
night.
Well as I knew the country, I finally made a false turn in the
confusing darkness, and approached the river when I thought we
were still several miles away from it and following its course.
Leaving Ned in safe hiding, I crept forward to reconnoiter. I made for
a rock overhanging the water, at the head of a bend in the river,
from the edge of which I hoped to be able to tell if the fires opposite
were repeated down the side I was on.
As I gained a sheltered place near the top and in the rear of the
rock, I heard a boat grate on the pebbles beneath, and two men
ascended to the very spot I had started for. I lay low behind the
scanty bushes, while they sat down near me. From what they said, I
gathered that they had crossed from the Rebel camp over the river
to investigate the bank up stream for some purpose, but not liking
the looks of something that had attracted their notice, they had
stopped there to decide what they should do.
I was too near to move away without them hearing me. I was
caught in a trap. Chaffing at a delay, when every moment was
precious, and fearing that Ned, alarmed at my protracted absence,
might come to look for me, I was obliged to crouch, motionless in
my hiding place, while the two men so near me idly discussed topics
relating to everything but the duty they were on. While I waited, the
clouds began to break away, and once or twice the moonlight shone
out full and strong, leaving me with little to shield me, had they
chanced to turn around.
68. Finally, after what seemed hours to me, one decided to go over for
re-enforcements and descended to the boat. Cautiously rising, as the
other advanced to the extreme edge of the rock, I saw that his back
was toward me and that he was intently watching the progress of
the boat, then in mid-stream.
It was possible then for me to have slipped away unnoticed, but I
was exasperated beyond endurance. An uncontrollable impulse
seized me. Even if I had been sure that the whole Confederate army
would have started to his rescue, I could not have helped pushing
that man into the water. Moving noiselessly behind him, with the end
of my revolver I gave him a sharp punch in the middle of the back.
Taken completely off his guard, without a word, but with a wild whirl
of arms and legs, he went straight down into the deep water
beneath. I have wondered hundreds of times since, what that man
thought was the matter with him. If he has lived to read this, he
knows now.
69. CHAPTER XIV.
I returned to where Ned was, and we began retracing our steps.
Although we made frequent attempts to get news, it was not until
nearly morning that I learned that our troops had advanced to a
point, nearer the place where I had made my way into the enemy's
camp, and, consequently, nearer where I was then, but to my left.
We immediately changed our route.
From the moment the order had fallen into my hands, my one desire
and aim was to get it where the information it contained, together
with what other I had gathered, could be put to instant use. Every
nerve throbbed with impatience. Every delay was intolerable. Yet
that entire ride back was a series of vexatious and dangerous delays.
I was beset on every side by dangers, which closed in on me at
every point where I tried to evade them. Every mile counted for four
in my eagerness to get on. I was obliged, time after time, to retrace
my steps and make long detours to avoid running into bodies of
skirmishers, to escape the vigilance of pickets, and to baffle the
pursuers on our tracks.
Twice that night we stood with our coats drawn tightly over our
horses' heads to keep them from making a sound to betray our
presence to the enemy, passing so closely below that by stooping,
we could have lifted the hats off of their heads with a ramrod.
Shortly after daybreak, as the first rays of of the sun showed over a
neighboring hill, I lay in a hollow log, while a man from the column
of passing soldiers sat on it to beat the dirt and stones from his
remnants of shoes. The dust from the inside of the log, loosened by
his pounding, choked me, until in my efforts to keep from coughing,
I bit through the sleeve of my coat, and left the print of my teeth on
70. my arm. About six hundred soldiers marched past me, as I watched
them from a crevice in the log.
Across the road and half way up the hill beyond I could see where
Ned crouched, keeping the horses back in the shelter of a low
thicket. Knowing exactly where to look for him, he stood out with
terrible distinctness to my abnormally keen sight, and I trembled
whenever I saw a soldier turn his head in that direction.
Even now, as I think it over, with all my increased experience and
knowledge of hair-breadth escapes, it seems simply incredible that
we ever got through. But get through we did.
By eight o'clock, exhausted to faintness from hard riding, lack of
food and loss of sleep, and with horses reeling from fatigue, we
turned out onto a road which in a few minutes took us beyond
danger. Loyal hands placed fresh horses at our disposal, and with
little loss of time, we were covering the last ten miles of our ride.
Soon the bit of paper, that "Lost Dispatch," which through all that
long and fearful night had been the elixir that nerved me to my
work, was in the hands of the proper officer, and I had
communicated to him the additional information I had gathered.
Both information and dispatch, without delay, were carried to the
Commander in Chief.
I only did my duty. My responsibility ended there. But looking back
now, it seems, as it did then, that better results should have been
obtained through a quick action on the intelligence gathered.
THE END.
71. *** END OF THE PROJECT GUTENBERG EBOOK THE LOST
DISPATCH ***
Updated editions will replace the previous one—the old editions will
be renamed.
Creating the works from print editions not protected by U.S.
copyright law means that no one owns a United States copyright in
these works, so the Foundation (and you!) can copy and distribute it
in the United States without permission and without paying
copyright royalties. Special rules, set forth in the General Terms of
Use part of this license, apply to copying and distributing Project
Gutenberg™ electronic works to protect the PROJECT GUTENBERG™
concept and trademark. Project Gutenberg is a registered trademark,
and may not be used if you charge for an eBook, except by following
the terms of the trademark license, including paying royalties for use
of the Project Gutenberg trademark. If you do not charge anything
for copies of this eBook, complying with the trademark license is
very easy. You may use this eBook for nearly any purpose such as
creation of derivative works, reports, performances and research.
Project Gutenberg eBooks may be modified and printed and given
away—you may do practically ANYTHING in the United States with
eBooks not protected by U.S. copyright law. Redistribution is subject
to the trademark license, especially commercial redistribution.
START: FULL LICENSE
73. PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK
To protect the Project Gutenberg™ mission of promoting the free
distribution of electronic works, by using or distributing this work (or
any other work associated in any way with the phrase “Project
Gutenberg”), you agree to comply with all the terms of the Full
Project Gutenberg™ License available with this file or online at
www.gutenberg.org/license.
Section 1. General Terms of Use and
Redistributing Project Gutenberg™
electronic works
1.A. By reading or using any part of this Project Gutenberg™
electronic work, you indicate that you have read, understand, agree
to and accept all the terms of this license and intellectual property
(trademark/copyright) agreement. If you do not agree to abide by all
the terms of this agreement, you must cease using and return or
destroy all copies of Project Gutenberg™ electronic works in your
possession. If you paid a fee for obtaining a copy of or access to a
Project Gutenberg™ electronic work and you do not agree to be
bound by the terms of this agreement, you may obtain a refund
from the person or entity to whom you paid the fee as set forth in
paragraph 1.E.8.
1.B. “Project Gutenberg” is a registered trademark. It may only be
used on or associated in any way with an electronic work by people
who agree to be bound by the terms of this agreement. There are a
few things that you can do with most Project Gutenberg™ electronic
works even without complying with the full terms of this agreement.
See paragraph 1.C below. There are a lot of things you can do with
Project Gutenberg™ electronic works if you follow the terms of this
agreement and help preserve free future access to Project
Gutenberg™ electronic works. See paragraph 1.E below.
74. 1.C. The Project Gutenberg Literary Archive Foundation (“the
Foundation” or PGLAF), owns a compilation copyright in the
collection of Project Gutenberg™ electronic works. Nearly all the
individual works in the collection are in the public domain in the
United States. If an individual work is unprotected by copyright law
in the United States and you are located in the United States, we do
not claim a right to prevent you from copying, distributing,
performing, displaying or creating derivative works based on the
work as long as all references to Project Gutenberg are removed. Of
course, we hope that you will support the Project Gutenberg™
mission of promoting free access to electronic works by freely
sharing Project Gutenberg™ works in compliance with the terms of
this agreement for keeping the Project Gutenberg™ name associated
with the work. You can easily comply with the terms of this
agreement by keeping this work in the same format with its attached
full Project Gutenberg™ License when you share it without charge
with others.
1.D. The copyright laws of the place where you are located also
govern what you can do with this work. Copyright laws in most
countries are in a constant state of change. If you are outside the
United States, check the laws of your country in addition to the
terms of this agreement before downloading, copying, displaying,
performing, distributing or creating derivative works based on this
work or any other Project Gutenberg™ work. The Foundation makes
no representations concerning the copyright status of any work in
any country other than the United States.
1.E. Unless you have removed all references to Project Gutenberg:
1.E.1. The following sentence, with active links to, or other
immediate access to, the full Project Gutenberg™ License must
appear prominently whenever any copy of a Project Gutenberg™
work (any work on which the phrase “Project Gutenberg” appears,
or with which the phrase “Project Gutenberg” is associated) is
accessed, displayed, performed, viewed, copied or distributed:
75. This eBook is for the use of anyone anywhere in the United
States and most other parts of the world at no cost and with
almost no restrictions whatsoever. You may copy it, give it away
or re-use it under the terms of the Project Gutenberg License
included with this eBook or online at www.gutenberg.org. If you
are not located in the United States, you will have to check the
laws of the country where you are located before using this
eBook.
1.E.2. If an individual Project Gutenberg™ electronic work is derived
from texts not protected by U.S. copyright law (does not contain a
notice indicating that it is posted with permission of the copyright
holder), the work can be copied and distributed to anyone in the
United States without paying any fees or charges. If you are
redistributing or providing access to a work with the phrase “Project
Gutenberg” associated with or appearing on the work, you must
comply either with the requirements of paragraphs 1.E.1 through
1.E.7 or obtain permission for the use of the work and the Project
Gutenberg™ trademark as set forth in paragraphs 1.E.8 or 1.E.9.
1.E.3. If an individual Project Gutenberg™ electronic work is posted
with the permission of the copyright holder, your use and distribution
must comply with both paragraphs 1.E.1 through 1.E.7 and any
additional terms imposed by the copyright holder. Additional terms
will be linked to the Project Gutenberg™ License for all works posted
with the permission of the copyright holder found at the beginning
of this work.
1.E.4. Do not unlink or detach or remove the full Project
Gutenberg™ License terms from this work, or any files containing a
part of this work or any other work associated with Project
Gutenberg™.
1.E.5. Do not copy, display, perform, distribute or redistribute this
electronic work, or any part of this electronic work, without
prominently displaying the sentence set forth in paragraph 1.E.1
76. with active links or immediate access to the full terms of the Project
Gutenberg™ License.
1.E.6. You may convert to and distribute this work in any binary,
compressed, marked up, nonproprietary or proprietary form,
including any word processing or hypertext form. However, if you
provide access to or distribute copies of a Project Gutenberg™ work
in a format other than “Plain Vanilla ASCII” or other format used in
the official version posted on the official Project Gutenberg™ website
(www.gutenberg.org), you must, at no additional cost, fee or
expense to the user, provide a copy, a means of exporting a copy, or
a means of obtaining a copy upon request, of the work in its original
“Plain Vanilla ASCII” or other form. Any alternate format must
include the full Project Gutenberg™ License as specified in
paragraph 1.E.1.
1.E.7. Do not charge a fee for access to, viewing, displaying,
performing, copying or distributing any Project Gutenberg™ works
unless you comply with paragraph 1.E.8 or 1.E.9.
1.E.8. You may charge a reasonable fee for copies of or providing
access to or distributing Project Gutenberg™ electronic works
provided that:
• You pay a royalty fee of 20% of the gross profits you derive
from the use of Project Gutenberg™ works calculated using the
method you already use to calculate your applicable taxes. The
fee is owed to the owner of the Project Gutenberg™ trademark,
but he has agreed to donate royalties under this paragraph to
the Project Gutenberg Literary Archive Foundation. Royalty
payments must be paid within 60 days following each date on
which you prepare (or are legally required to prepare) your
periodic tax returns. Royalty payments should be clearly marked
as such and sent to the Project Gutenberg Literary Archive
Foundation at the address specified in Section 4, “Information
77. about donations to the Project Gutenberg Literary Archive
Foundation.”
• You provide a full refund of any money paid by a user who
notifies you in writing (or by e-mail) within 30 days of receipt
that s/he does not agree to the terms of the full Project
Gutenberg™ License. You must require such a user to return or
destroy all copies of the works possessed in a physical medium
and discontinue all use of and all access to other copies of
Project Gutenberg™ works.
• You provide, in accordance with paragraph 1.F.3, a full refund of
any money paid for a work or a replacement copy, if a defect in
the electronic work is discovered and reported to you within 90
days of receipt of the work.
• You comply with all other terms of this agreement for free
distribution of Project Gutenberg™ works.
1.E.9. If you wish to charge a fee or distribute a Project Gutenberg™
electronic work or group of works on different terms than are set
forth in this agreement, you must obtain permission in writing from
the Project Gutenberg Literary Archive Foundation, the manager of
the Project Gutenberg™ trademark. Contact the Foundation as set
forth in Section 3 below.
1.F.
1.F.1. Project Gutenberg volunteers and employees expend
considerable effort to identify, do copyright research on, transcribe
and proofread works not protected by U.S. copyright law in creating
the Project Gutenberg™ collection. Despite these efforts, Project
Gutenberg™ electronic works, and the medium on which they may
be stored, may contain “Defects,” such as, but not limited to,
incomplete, inaccurate or corrupt data, transcription errors, a
copyright or other intellectual property infringement, a defective or
78. damaged disk or other medium, a computer virus, or computer
codes that damage or cannot be read by your equipment.
1.F.2. LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except for
the “Right of Replacement or Refund” described in paragraph 1.F.3,
the Project Gutenberg Literary Archive Foundation, the owner of the
Project Gutenberg™ trademark, and any other party distributing a
Project Gutenberg™ electronic work under this agreement, disclaim
all liability to you for damages, costs and expenses, including legal
fees. YOU AGREE THAT YOU HAVE NO REMEDIES FOR
NEGLIGENCE, STRICT LIABILITY, BREACH OF WARRANTY OR
BREACH OF CONTRACT EXCEPT THOSE PROVIDED IN PARAGRAPH
1.F.3. YOU AGREE THAT THE FOUNDATION, THE TRADEMARK
OWNER, AND ANY DISTRIBUTOR UNDER THIS AGREEMENT WILL
NOT BE LIABLE TO YOU FOR ACTUAL, DIRECT, INDIRECT,
CONSEQUENTIAL, PUNITIVE OR INCIDENTAL DAMAGES EVEN IF
YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH DAMAGE.
1.F.3. LIMITED RIGHT OF REPLACEMENT OR REFUND - If you
discover a defect in this electronic work within 90 days of receiving
it, you can receive a refund of the money (if any) you paid for it by
sending a written explanation to the person you received the work
from. If you received the work on a physical medium, you must
return the medium with your written explanation. The person or
entity that provided you with the defective work may elect to provide
a replacement copy in lieu of a refund. If you received the work
electronically, the person or entity providing it to you may choose to
give you a second opportunity to receive the work electronically in
lieu of a refund. If the second copy is also defective, you may
demand a refund in writing without further opportunities to fix the
problem.
1.F.4. Except for the limited right of replacement or refund set forth
in paragraph 1.F.3, this work is provided to you ‘AS-IS’, WITH NO
OTHER WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED,
79. INCLUDING BUT NOT LIMITED TO WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR ANY PURPOSE.
1.F.5. Some states do not allow disclaimers of certain implied
warranties or the exclusion or limitation of certain types of damages.
If any disclaimer or limitation set forth in this agreement violates the
law of the state applicable to this agreement, the agreement shall be
interpreted to make the maximum disclaimer or limitation permitted
by the applicable state law. The invalidity or unenforceability of any
provision of this agreement shall not void the remaining provisions.
1.F.6. INDEMNITY - You agree to indemnify and hold the Foundation,
the trademark owner, any agent or employee of the Foundation,
anyone providing copies of Project Gutenberg™ electronic works in
accordance with this agreement, and any volunteers associated with
the production, promotion and distribution of Project Gutenberg™
electronic works, harmless from all liability, costs and expenses,
including legal fees, that arise directly or indirectly from any of the
following which you do or cause to occur: (a) distribution of this or
any Project Gutenberg™ work, (b) alteration, modification, or
additions or deletions to any Project Gutenberg™ work, and (c) any
Defect you cause.
Section 2. Information about the Mission
of Project Gutenberg™
Project Gutenberg™ is synonymous with the free distribution of
electronic works in formats readable by the widest variety of
computers including obsolete, old, middle-aged and new computers.
It exists because of the efforts of hundreds of volunteers and
donations from people in all walks of life.
Volunteers and financial support to provide volunteers with the
assistance they need are critical to reaching Project Gutenberg™’s
goals and ensuring that the Project Gutenberg™ collection will
80. remain freely available for generations to come. In 2001, the Project
Gutenberg Literary Archive Foundation was created to provide a
secure and permanent future for Project Gutenberg™ and future
generations. To learn more about the Project Gutenberg Literary
Archive Foundation and how your efforts and donations can help,
see Sections 3 and 4 and the Foundation information page at
www.gutenberg.org.
Section 3. Information about the Project
Gutenberg Literary Archive Foundation
The Project Gutenberg Literary Archive Foundation is a non-profit
501(c)(3) educational corporation organized under the laws of the
state of Mississippi and granted tax exempt status by the Internal
Revenue Service. The Foundation’s EIN or federal tax identification
number is 64-6221541. Contributions to the Project Gutenberg
Literary Archive Foundation are tax deductible to the full extent
permitted by U.S. federal laws and your state’s laws.
The Foundation’s business office is located at 809 North 1500 West,
Salt Lake City, UT 84116, (801) 596-1887. Email contact links and up
to date contact information can be found at the Foundation’s website
and official page at www.gutenberg.org/contact
Section 4. Information about Donations to
the Project Gutenberg Literary Archive
Foundation
Project Gutenberg™ depends upon and cannot survive without
widespread public support and donations to carry out its mission of
increasing the number of public domain and licensed works that can
be freely distributed in machine-readable form accessible by the
widest array of equipment including outdated equipment. Many
81. small donations ($1 to $5,000) are particularly important to
maintaining tax exempt status with the IRS.
The Foundation is committed to complying with the laws regulating
charities and charitable donations in all 50 states of the United
States. Compliance requirements are not uniform and it takes a
considerable effort, much paperwork and many fees to meet and
keep up with these requirements. We do not solicit donations in
locations where we have not received written confirmation of
compliance. To SEND DONATIONS or determine the status of
compliance for any particular state visit www.gutenberg.org/donate.
While we cannot and do not solicit contributions from states where
we have not met the solicitation requirements, we know of no
prohibition against accepting unsolicited donations from donors in
such states who approach us with offers to donate.
International donations are gratefully accepted, but we cannot make
any statements concerning tax treatment of donations received from
outside the United States. U.S. laws alone swamp our small staff.
Please check the Project Gutenberg web pages for current donation
methods and addresses. Donations are accepted in a number of
other ways including checks, online payments and credit card
donations. To donate, please visit: www.gutenberg.org/donate.
Section 5. General Information About
Project Gutenberg™ electronic works
Professor Michael S. Hart was the originator of the Project
Gutenberg™ concept of a library of electronic works that could be
freely shared with anyone. For forty years, he produced and
distributed Project Gutenberg™ eBooks with only a loose network of
volunteer support.
82. Project Gutenberg™ eBooks are often created from several printed
editions, all of which are confirmed as not protected by copyright in
the U.S. unless a copyright notice is included. Thus, we do not
necessarily keep eBooks in compliance with any particular paper
edition.
Most people start at our website which has the main PG search
facility: www.gutenberg.org.
This website includes information about Project Gutenberg™,
including how to make donations to the Project Gutenberg Literary
Archive Foundation, how to help produce our new eBooks, and how
to subscribe to our email newsletter to hear about new eBooks.
83. Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.
More than just a book-buying platform, we strive to be a bridge
connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.
Join us on a journey of knowledge exploration, passion nurturing, and
personal growth every day!
ebookbell.com