paint-brush
Six ‘Java 9’ API Improvements You Should Knowby@thecompetenza
283 reads

Six ‘Java 9’ API Improvements You Should Know

by Competenza InnovareAugust 29th, 2021
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Java 9 has transformed the way Java developers write code to develop Java-based applications. The Java language is making enhancements periodically to be in the market for a longer time. Java 9 comes with the Stream takeWhile() method to improve the stream API in Java. We will be discussing the following listed API improvements in Java 9: Stream API Improvements, Multiresolution Image API Improvements and Completable Future API Improvements. Java is a widely used programming language across the globe and is one of the widely used languages.

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - Six ‘Java 9’ API Improvements You Should Know
Competenza Innovare HackerNoon profile picture

In the year 2021, Java turned 26 years old.


Yes, Java is a pretty old programming language. Still, it holds popularity in the software development landscape and is one of the widely used programming languages across the globe.


Source: TIOBE Index


Source: PYPL


The majority of Fortune 500 enterprises use this programming language. The Java language is making enhancements periodically to be in the market for a longer time.


Java 9 has transformed the way Java developers write code to develop Java-based applications. It has come up with lots of improvements to existing APIs.


We will be discussing the following listed API improvements in Java 9:


  1. Stream API Improvements
  2. Process API Improvements
  3. Multiresolution Image API
  4. CompletableFuture API Improvements
  5. Optional Class Improvements
  6. Collection Factory Methods


Let's deep dive into the API improvements of Java 9.


1. Stream API Improvements

In Java, streams were introduced to assist Java application developers to perform aggregate operations from a collection of objects by using various methods. In order to improve stream API, Java 9 comes with some new methods.


Let’s talk about the new methods added to the stream interface in Java 9 to improve the stream API.


a) Java Stream Iterate Method

The iterate method is introduced to the Java 9 stream interface. It allows you to iterate stream elements till the given condition. The iteration of stream elements stops as soon as the predicate (condition) returns false.


This method takes three parameters- seed, hasNext and next.


seed: Indicates an initial element.


hasNext: It is a condition (predicate) that applies to elements to verify when the stream must end.


next: It is a function to be applied to the previous stream element to generate a new stream element.


import java.util.stream.Stream;

public class StreamExample

{

  public static void main(String[] args)

  {  
   Stream.iterate(1, i -> i <= 10, i -> i\*3)

  .forEach(System.out::println);
  }
}


Output: [1, 3, 9]


b) Java Stream dropWhile() Method

Stream dropWhile method gives the outcome based on the order of the stream elements.


Ordered stream: In an ordered stream, the dropWhile() method returns a stream that consists of elements after removing the elements that match the specified predicate (condition).


Unordered stream: In an unordered stream, this method returns a stream that consists of leftover elements of this stream after removing a subset of elements that match the specified predicate.


Implementation of Stream dropWhile() Method:



import java.util.List;

import java.util.stream.Collectors;

import java.util.stream.Stream;

public class StreamExample {

  public static void main(String[] args) {
    List<Integer> list

      = Stream.of(2,2,3,4,5,6,7,8,9,10)

        .dropWhile(i -> (i % 2 == 0)).collect(Collectors.toList());
   System.out.println(list);

   }

}



Output: [3, 4, 5, 6, 7, 8, 9, 10]


c) Java Stream takeWhile() Method


Java 9 comes with the Stream takeWhile method to improve the stream API in Java. The method returns every element until the predicate (condition) unmatched the elements. And the program ends just when it fails to satisfy the predicate.


-Implementation of Stream takeWhile() Method:

import java.util.List;

import java.util.stream.Collectors;

import java.util.stream.Stream;

public class StreamExample {

  public static void main(String[] args) {
   List<Integer> list
   = Stream.of(1,2,3,4,5,6,7,8,9,10)
      .takeWhile(i -> (i % 2 == 0)).collect(Collectors.toList());
  System.out.println(list);

  }

}



Output: []

Here, takeWhile() method returns an empty list because the condition is not matched at first list element, and the method terminates here.


-Implementation of Stream takeWhile() Method:



import java.util.List;

import java.util.stream.Collectors;

import java.util.stream.Stream;

public class StreamExample {

  public static void main(String[] args) {
    List<Integer> list
    = Stream.of(2,2,3,4,5,6,7,8,9,10)
       .takeWhile(i -> (i % 2 == 0)).collect(Collectors.toList());
   System.out.println(list);

  }

}



Output: [2,2]


Here, the method returns the first two elements because the condition matched for the first 2 elements (even elements), and the third element failed to satisfy the condition. So, the program ends at the third element.


d) Java 9 Stream ofNullable Method


Prior to Java 9, you couldn’t make a stream using a null value, it would throw NullPointerException error.


To handle this error, Java 9 has added a Stream ofNullable method to the stream interface. This method returns a sequential stream that consists of a single element if the parameter of the method is non-null. And the method returns an empty stream for a null parameter.


Implementation of Stream ofNullable Method:
import java.util.stream.Stream;

  public class StreamExample {
    public static void main(String\[\] args) {
      Stream<Integer> val
      = Stream.ofNullable(null);
    val.forEach(System.out::println);
  }

}



This code will not give any result.


2. Process API Improvements

The process API in Java helps in managing and controlling Operating system processes. In the older versions, managing OS processes was a cumbersome task to do for developers. With the advent of Java 9, the process API has improved a lot.


In Java 9, some new classes and interfaces are introduced for interacting and managing OS.

Two new interfaces have been introduced to the JDK:



Java ProcessHandle Interface


ProcessHandle interface helps developers to manage and control processes. With a slew of static factory methods in this interface, you can monitor every process for aliveness, list its children, process ID, current direct children of the process, the killing of the process, and many more.


Signature of Java ProcessHandle Interface


public interface ProcessHandle extends Comparable<ProcessHandle>


Source


Java ProcessHandle.Info Interface


Java 9 has introduced this new interface to give information about the processes. This newly added interface is the nested interface of the ProcessHandle interface.


Signature of Java ProcessHandle.Info Interface


public static interface ProcessHandle.Info


We have tabled various methods in ProcessHandle.Info interface.


Source


3. Multiresolution Image API

Java 9 brings a new multi-resolution image API that supports multiple images with different image resolution variants. This Java 9 API allows a group of images with different resolutions to be used as a single multi-resolution image.


We have listed down the important methods of multi-resolution images.


Image getResolutionVariant(double destImageWidth, double destImageHeight)


Gets a specific image which is the best variant to represent this logical image at the indicated size.


List<Image> getResolutionVariants() – This method returns a readable list of all resolution variants.


4. CompletableFuture API Improvements

A CompletableFuture is a type of class in Java that belongs to java.util.concurrent package. This class implements CompletionStage and Future interface. It was introduced in Java 8.


Java developers use this class for asynchronous programming which means to write non-blocking code.


It runs a task on a thread other than the main application thread. And also sends a notification to the main thread about its task status whether the task is in progress, completed, or failed.


In this way, the main thread does not wait for the task to get over. Lots of other tasks run in parallel. This helps in enhancing the performance of an application.


Java 9 brings some enhancements to the CompletableFuture API.


  • Support for delays and timeouts
  • Enhanced support for subclassing
  • Addition of New factory methods

5. Optional Class Improvements

Optional Class is a public final class in Java. This class was introduced in Java 8 to avoid null checks and NullPointerException issues. Java developers need to import java.util package to use the Optional class in your applications. This class provides methods to check whether a value is present for a particular variable or not.


Java 9 brings 3 new methods to enhance its functionality. Let’s have a look at these methods.


  • stream()

public Stream<T> stream()


If there is any value, it will return a sequential Stream consists of that value, otherwise returns an empty Stream.


  • ifPresentOrElse()


public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)


If there is any value, this method will perform the given task with the given value, otherwise performs the given empty-based action.


  • or()


public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier)


If there is any value, the method will return an Optional describing the value, otherwise returns an Optional generated by the supplying function.


6. Collection Factory Methods


Previously, for creating a list of 5 elements, developers used to write the following code.



import java.util.ArrayList;

import java.util.List;

public class FactoryMethodsExample {

  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("Java");
    list.add("JavaFX");
    list.add("Spring");
    list.add("Hibernate");
    list.add("JSP");
    for(String l : list){
      System.out.println(l);
     }
   }

}



Output:


Spring JavaFX JSP Java Hibernate


As you can see, in the above-written code, add method is called frequently for each list element.


Here comes the improvised version of doing the same task. In Java 9, you can do it in a better way with the help of collection factory methods.


So, what are these Factory methods?


Well, Factory methods are a special kind of static method that assists developers to make unmodifiable instances of collections in Java. By the collection Factory methods, you can make list, set, and map a small number of elements.


Signature of Java 9 Set & List Interface Factory Methods


Based on the number of parameters, it will return an immutable set of elements. static <E> Set<E> of() static <E> Set<E> of(E e1) static <E> Set<E> of(E e1, E e2) // ....and so on


It returns an immutable set comprised of a random number of elements. static <E> Set<E> of(E... elements)


Similarly, for List interface:

static <E> List<E> of() static <E> List<E> of(E e1) static <E> List<E> of(E e1, E e2) // ....and so on


static <E> List<E> of(E... elements)


Generally, 10 elements are enough. In case, more than 10 are needed, you can make use of the var-args version.


But you might be thinking, what is the use of 11 overloading methods if you have a var-args version that can return n number of elements.


Well, the performance factor is the answer to your query.


Every var-args method call implicitly makes an array. While overloading methods do not create objects unnecessary and thus avoid garbage collection overhead.


Implementation of Java 9 Set Interface Factory Method:



import java.util.Set;
public class FactoryMethodsExample {
  public static void main(String[] args) {
    Set<String> set = Set.of("Java","JavaFX","Spring","Hibernate","JSP");
    for(String l:set) {
     System.out.println(l);
    }
  }
}



Output:

Spring JavaFX JSP Java Hibernate


Java 9 Map Interface Factory Methods


Map Interface


In Java 9, Map interface has two factory methods- Map.of() and Map.ofEntries() that assist Java developers to build immutable maps seamlessly.


Implementation of Java 9 Map Interface Factory Method:

import java.util.Map;
public class FactoryMethodsExample {
  public static void main(String[] args) {
    // Creating Map Entry
    Map.Entry<Integer, String> e1 = Map.entry(101, "Java");
    Map.Entry<Integer, String> e2 = Map.entry(102, "Spring");
    // Creating Map using map entries
    Map<Integer, String> map = Map.ofEntries(e1,e2);
    // Iterating Map
    for(Map.Entry<Integer, String> m : map.entrySet()){
      System.out.println(m.getKey()+" "+m.getValue());
    }
  }
}


Output:

102 Spring 101 Java


We have listed the common characteristics of Factory method for set, list, and map instance:

  • It is immutable
  • No null elements
  • It is serializable ( if all the elements are serializable)
  • No duplicate elements.
  • The iteration order of set elements is not specific and it might vary.


Points to Ponder:


  • For List and Set interfaces, of() method is overloaded to take 0 to 10 parameters and one with var args parameter.

  • For Map interface, of() method is overloaded to have 0 to 10 Key-value pairs.

  • And if there are more than 10 key-value pairs for Map interface, you can use ofEntries() method by taking var args parameter.


Wrapping Up

Hope you have learned about the API improvements in Java 9. These API improvements will assist you to write better code for your Java-based application development projects.


Happy learning!