There are a few ūüŹÜ treasures that have been added as a part of JDK 11 and help developers to minimize coding efforts. Some of them you definitely know such as responsive Http2/API, you can run the source code directly without compiling. However, have you tried extensions of common classes such as String, Optional, Collections and Files, and if you haven’t already, congratulations, you’ll learn about some of them in this article.

You can download the JDK 11 from this link.

1. Local parameter type inference for Lambda Expressions

JDK 11 allows var keyword to be used when declaring the formal parameters of implicitly typed lambda expressions:

Function<String, String> append = (var string) -> string + " World";
String appendedString = append.apply("Hello");

It’s not just adding the var keyword to the variable that omits the type. The JDK 11 also allow annotations to be added to lambda’s parameters without having to write full variable type name. Let’s take a look at with example:

Function<String, String> append = (@NonNull var string) -> string + " World";
String appendedString = append.apply("Hello");

// Output of above program
Hello World

Now the apply method inside the Function accepts the NonNull value.

2. Usage of String:: repeat method to copy a String

A String method for repeating sequences of characters has been long requested from a user in StackOverflow.


Now from JDK 11, we have a repeat method that does exactly what we need.

var str = "abc";
var repeated = str.repeat(3);

// Output of above program

3. Create a Path with Path::of method

I really like the Path API, which solves the problem of switching between paths, URIs, URLs, and FILEs. In Java 11 we can use Paths::get and Path::of methods to make them very uniform.

Path googlePath = Path.of(URI.create(""))
Path studentFilePath = Path.of("/home/Students/student.txt")

4. Files::readString and Files::writeString for file reading and Writing

If you need to read content from a very large file, we generally use lines method which returns a lazy stream. Similarly, if you want to store content in a file at the same time, I usually write to the files using the write method by passing an Iterable.

But in JDK 11, two methods of readString and writeString have been added to Files class.

String studentFileContent = Files.readString(Path.of("student.txt"))
String modifiedStudentContent = addNewSubject(studentFileContent)

5. String::lines to get the number of data Rows

You have a multi-line string and you want to do a separate operation for each line. You can do this with String::lines method.

var multiline = "My\nname is\nahsen saeed";
Stream<String> stream = multiline.lines();

// Output of above program

The lines in the Stream are in the order in which they occur in the string. Unlike split, the new lines method is lazy.

Note: The new line in a string in the above example uses \n¬†in Windows. Although, I’m using it in Linux, lines method can still split them. In a different operating system, the lines method will use \r, \n, \r\n as terminators. Even if we mix them in a string.

6. Usage of Optional::isEmpty instead of isPresent

Almost in every application, we need to check that if the value exists or not and for that, we often use the Optional::isPresent method. I know! there is no problem in writing that, but writing does not understand the meaning of well. Now if we need to check that the value is empty inside the Optional::isPresent method then we add the ! operator at the front.

val optional: Optional<String> = Optional.empty()
    // value is empty

This ! is easily forgotten on Optional starting with Java 11, we have a better solution.

val optional: Optional<String> = Optional.empty()
    if (optional.isEmpty) {
        //  value is empty

The isEmpty method is used to return true if the value is not present.

7. Handling regular expressions with Pattern::asMatchPredicate

You have a regular expression and want to do some filtering based on it. What do you do?

Pattern<String> chracterPredicate = Pattern.compile("ah").asPredicate();

// Output of above program

We had the asPredicate method as part of JDK 8, which will create a Predicate if and only if the given Pattern is found in a given string.

In JDK 11 we’ve another method Pattern::asMatchPredicate. So, what is the difference between them:

  • asPredicate: Under the hood, the asPredicate method called¬† matcher(s).find().
  • asMatchPredicate: It will checks if the entire string conforms to this regular expression. This method behaves like matcher(s).matches().

Now let’s say you have a regular expression that verifies the email.

private static final String EMAIL_PATTERN = "^[a-zA-Z0-9#_~!$&'()*+,;=:.\"<>@\\[\\]\\\\][email protected][a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*$";

var pattern = Pattern.compile(EMAIL_PATTERN).asMatchPredicate();
Stream.of("[email protected]")

You see the asMatchPredicate method checks our regular expression internally and return the email if it is matched with the regular expression.

8. Usage of the strip, stripLeading, and stripTrailing

JDK 11 introduces the strip methods, which have some subtle differences from trim, let’s see them one by one:

8.1 strip

The strip() method is used to remove the leading and trailing whitespaces. It is helpful to remove the white space from the beginning and the end of a string.

var s = " Michale ";
String stripResult = s.strip(); 

// Output of above program

8.2 stripLeading

The stripLeading() method is used to remove the white space from the beginning of a string.

var s = " Michale ";
String stripLeadingResult = s.stripLeading();

// Output o above program
"Michale "

8.3 stripTrailing

The stripTrailing() method is used to remove the white spaces from the end of a string.

var s = " Michale ";
String stripTrailingResult = s.stripTrailing();

// Output of above program
" Michale"

9. Handle empty I/O operations with null StreamReader

What do you do when you need an InputStream that doesn’t process any data? What about an empty OutputStream, Reader or maybe Writer? In Java 11 you can do the following conversions:

InputStream inputStream = InputStream.nullInputStream();
OutputStream outputStream = OutputStream.nullOutputStream();
Reader reader = Reader.nullReader();
Writer writer = Writer.nullWriter();

10. Convert collections to arrays using Collection::toArray

How did you turn the collection into an array before Java 11?

Studen[] studentArray = studentList.toArray(new Student[0]);

The above toArray method returns an array if the list fits in the specified array. Otherwise, a new array is allocated with the runtime type of the specified array and size of the list.

Now that we have a method which returns an array of specified type T. Why do we need another function? Is there a better way to handle it? In Java 11, you can do this:

Student[] studentArray = studentList.toArray(Student[]::new);

This is a new overloading method used by collection classes to receive IntFunction. The above Collection::toArray method returns an array of the corresponding length based on the length of the input data. It can be expressed in a brief and clear manner as T[]::new.

What’s next

Closing Up

Hope you found this story useful and interesting. Feel free to share your feedback and comments below.

Thank you for being here and keep reading…


Disclosure of Material Connection: Some of the links in the post above are ‚Äúaffiliate links.‚ÄĚ This means if you click on the link and purchase the item, we will receive an affiliate commission. Regardless, we only recommend products or services we use personally and believe will add value to our readers.


I’m a mobile product devsigner (i.e. I consider myself as both a developer and a designer) and user experience/interface engineer. I’m an expert on the Android platform and have been recognized as it by the community.


  1. Mukhlis Ur Rehman

    Really appreciate your great work…