Java 11 API Additions: Files.readString, Predicate.not
Introduction
Besides the new String methodsClick to read tutorial: Java 11 String Methods: isBlank, lines, strip, repeat, Java 11 added a number of small methods across the core libraries which remove boilerplate from everyday code. This tutorial explains these Java 11 API additions with examples. We will start with
Before Java 11, reading a whole text file into a
OUTPUT of the above code
Explanation of the code
Predicate.not() and Pattern.asMatchPredicate()
Definition of Predicate.not()
Method referencesClick to read: Method references such as
OUTPUT of the above code
Explanation of the code
OUTPUT of the above code
Collection.toArray(IntFunction)
Definition of Collection.toArray(IntFunction)
Converting a collection to a typed array used to need
OUTPUT of the above code
Both give a
OUTPUT of the above code
Files.readString() and Files.writeString(), which read and write a text file in one line, along with Path.of(). We will then look at Predicate.not() and Pattern.asMatchPredicate() for filtering streams, Optional.isEmpty(), and Collection.toArray(IntFunction). Lastly, we will go through a few other additions such as TimeUnit.convert(Duration) and the null streams and writers.
Files.readString(), Files.writeString() and Path.of()
Definitions of the new Files and Path methods
public static Path writeString(Path path, CharSequence csq, OpenOption... options)public static String readString(Path path)public static Path of(String first, String... more)String needed new String(Files.readAllBytes(path), StandardCharsets.UTF_8), and writing one needed Files.write() with a byte array or a list of lines. Java 11 adds methods which do this directly. Both use UTF-8 by default, and have overloads which take a Charset. Path.of() is a new way to create a Path, which does the same thing as the older Paths.get() but sits on the Path interface itself.
Reading and writing text files in one line
//ReadWriteStringDemo.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
public class ReadWriteStringDemo {
public static void main(String[] args) throws IOException {
Path notes = Path.of("notes.txt");
Files.writeString(notes, "Java 11 was released in September 2018.\n");
Files.writeString(notes, "It is a long-term support release.\n", StandardOpenOption.APPEND);
String content = Files.readString(notes);
System.out.print(content);
System.out.println("Lines: " + content.lines().count());
Files.delete(notes);
}
}
Java 11 was released in September 2018. It is a long-term support release. Lines: 2
Path.of("notes.txt")creates a path relative to the current directory. It also accepts several parts, as inPath.of("data", "2026", "notes.txt").- The first
writeString()creates the file, or replaces its contents if it exists. PassingStandardOpenOption.APPENDadds to the end of the file instead. readString()returns the whole file as oneString, which we then split into lines with the newString.lines()method.readString()reads the entire file into memory, so it is meant for small and medium-sized files. For large files, process the lines one at a time withFiles.lines(). If the file is not valid UTF-8,readString()throws aMalformedInputExceptioninstead of silently replacing the bad bytes.
static <T> Predicate<T> not(Predicate<? super T> target)String::isBlank make stream filters short and readable, but there was no easy way to negate one. You had to fall back to a lambda, s -> !s.isBlank(), or write ((Predicate<String>) String::isBlank).negate(). The static method Predicate.not() solves this. Java 11 also added Pattern.asMatchPredicate(), which turns a regular expression into a predicate that tests whether the whole string matches.
Negating method references with Predicate.not()
//PredicateNotDemo.java
import java.util.List;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class PredicateNotDemo {
public static void main(String[] args) {
List<String> lines = List.of("Tom", " ", "Harry", "", "Sam42", "Ann");
List<String> nonBlank = lines.stream()
.filter(Predicate.not(String::isBlank))
.collect(Collectors.toList());
System.out.println("Not blank: " + nonBlank);
Predicate<String> onlyLetters = Pattern.compile("[A-Za-z]+").asMatchPredicate();
System.out.println("Only letters: " + nonBlank.stream().filter(onlyLetters).collect(Collectors.toList()));
System.out.println("Not only letters: " + nonBlank.stream().filter(Predicate.not(onlyLetters)).collect(Collectors.toList()));
}
}
Not blank: [Tom, Harry, Sam42, Ann] Only letters: [Tom, Harry, Ann] Not only letters: [Sam42]
Predicate.not(String::isBlank)keeps the strings which are not blank, dropping" "and"". With a static import ofjava.util.function.Predicate.not, this can be written as justfilter(not(String::isBlank)).asMatchPredicate()usesMatcher.matches(), so"Sam42"fails because the whole string must consist of letters. The olderasPredicate(), from Java 8, usesfind()and would accept any string which contains a letter.
isPresent() since Java 8. Java 11 adds its opposite, isEmpty(), which reads better than !optional.isPresent(), and can be used as a method reference -
Checking for an empty Optional
//OptionalIsEmptyDemo.java
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class OptionalIsEmptyDemo {
static final Map<String, String> EMAILS = Map.of("Tom", "tom@example.com");
static Optional<String> findEmail(String name) {
return Optional.ofNullable(EMAILS.get(name));
}
public static void main(String[] args) {
for (String name : List.of("Tom", "Harry")) {
Optional<String> email = findEmail(name);
if (email.isEmpty()) {
System.out.println(name + ": no email on record");
} else {
System.out.println(name + ": " + email.get());
}
}
long missing = List.of("Tom", "Harry", "Sam").stream()
.map(OptionalIsEmptyDemo::findEmail)
.filter(Optional::isEmpty)
.count();
System.out.println("Names without email: " + missing);
}
}
Tom: tom@example.com Harry: no email on record Names without email: 2
default <T> T[] toArray(IntFunction<T[]> generator)list.toArray(new String[0]). Java 11 adds an overload which takes an array constructor reference, in the same way as Stream.toArray()Click to read: Stream.toArray() -
Converting a collection to a typed array
//ToArrayDemo.java
import java.util.Arrays;
import java.util.List;
public class ToArrayDemo {
public static void main(String[] args) {
List<String> names = List.of("Tom", "Harry", "Sam");
String[] before = names.toArray(new String[0]); // before Java 11
String[] after = names.toArray(String[]::new); // Java 11
System.out.println(Arrays.toString(before) + " " + before.getClass().getSimpleName());
System.out.println(Arrays.toString(after) + " " + after.getClass().getSimpleName());
}
}
[Tom, Harry, Sam] String[] [Tom, Harry, Sam] String[]
String[]. The new form is shorter and makes the intent clearer. Note that the array constructor is called with a size of 0, and the result is then filled using toArray(T[]), so it is not faster than the old form.
Other additions in Java 11
TimeUnit.convert(Duration) and null streams
//OtherAdditionsDemo.java
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.Writer;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
public class OtherAdditionsDemo {
public static void main(String[] args) throws IOException {
// TimeUnit.convert(Duration)
Duration timeout = Duration.ofMinutes(2).plusSeconds(30);
System.out.println(TimeUnit.SECONDS.convert(timeout) + " seconds");
System.out.println(TimeUnit.MILLISECONDS.convert(timeout) + " milliseconds");
// Null streams, readers and writers
System.out.println("Bytes read: " + InputStream.nullInputStream().readAllBytes().length);
try (OutputStream sink = OutputStream.nullOutputStream()) {
sink.write("discarded".getBytes());
}
Writer discard = Writer.nullWriter();
long copied = new StringReader("Java 11").transferTo(discard);
System.out.println("Characters transferred to nullWriter: " + copied);
}
}
150 seconds 150000 milliseconds Bytes read: 0 Characters transferred to nullWriter: 7
TimeUnit.convert(Duration)converts ajava.time.Durationto a count of the given unit, which helps when calling older concurrency APIs that take alongand aTimeUnit.InputStream.nullInputStream(),OutputStream.nullOutputStream(),Reader.nullReader()andWriter.nullWriter()return streams which contain no data, or discard everything written to them. They are handy in tests, and when an API requires a stream whose output you do not need.
Files.readString() and Files.writeString(), and created paths with Path.of(). We negated method references with Predicate.not(), matched whole strings with Pattern.asMatchPredicate(), and checked for an empty value with Optional.isEmpty(). Lastly, we converted collections to typed arrays with toArray(String[]::new), and looked at TimeUnit.convert(Duration) and the null streams. In the next tutorial, we will look at the biggest API addition in Java 11 - the HTTP Client APIClick to read tutorial: Java 11 HTTP Client API Tutorial with Examples.Continue Reading Java 11 Tutorials
Java 11 HTTP Client API Tutorial with ExamplesClick to read tutorial: Java 11 HTTP Client API Tutorial with Examples Java 11: Run Single-File Source Code Programs with javaClick to read tutorial: Java 11: Run Single-File Source Code Programs with java Overview of New Features in Java 11Click to read tutorial: Overview of New Features in Java 11 Java 11 String Methods: isBlank, lines, strip, repeatClick to read tutorial: Java 11 String Methods: isBlank, lines, strip, repeat Java 11 var in Lambda Parameters with ExamplesClick to read tutorial: Java 11 var in Lambda Parameters with Examples Java 11 Removed Modules: Java EE, CORBA and JavaFXClick to read tutorial: Java 11 Removed Modules: Java EE, CORBA and JavaFX
Java 11 HTTP Client API Tutorial with ExamplesClick to read tutorial: Java 11 HTTP Client API Tutorial with Examples Java 11: Run Single-File Source Code Programs with javaClick to read tutorial: Java 11: Run Single-File Source Code Programs with java Overview of New Features in Java 11Click to read tutorial: Overview of New Features in Java 11 Java 11 String Methods: isBlank, lines, strip, repeatClick to read tutorial: Java 11 String Methods: isBlank, lines, strip, repeat Java 11 var in Lambda Parameters with ExamplesClick to read tutorial: Java 11 var in Lambda Parameters with Examples Java 11 Removed Modules: Java EE, CORBA and JavaFXClick to read tutorial: Java 11 Removed Modules: Java EE, CORBA and JavaFX