Skip to main content

How JDK 8 standardizes and augments to Guava library functionalities

Posted by bhaktimehta on July 14, 2014 at 4:11 AM PDT

JDK 8 introduced a lot of new features and improvements in the platform from Lamda expressions, Stream collection types,
Functional interfaces, Type annotations, Nashorn
etc.

Guava library from Google provided some support for functional programming idioms prior to JDK 8.
I have been using Guava for some of my projects. So here is a small write up on
how new functionality added in JDK 8 makes it possible to achieve standardized way to functionality offered by Google's Guava.
This article further highlights similarities and differences between the two APIs and was inspired by this discussion on google groups.

The following table shows some of the API which I will cover in detail wrt. Guava and JDK 8

Functionality Guava JDK 8
Predicate apply(T input) test(T input)
Combining predicates Predicates.and/or/not Predicate.and/or/negate
Supplier Suplier.get Supplier.get
Joiner/StringJoiner Joiner.join() StringJoiner.add()
SettableFuture/CompletableFuture SettableFuture.set(T input) CompletableFuture.complete(T input)
Optional Optional.of/ofNullable/empty Optional.of/fromNullable/absent

Source Code

The following code snippets are part of a complete sample available at https://github.com/bhakti-mehta/samples/tree/master/jdk8-and-guava
For the sake of simplicty, I have a simple sample which has a collection of people's data.
We start with a simple POJO Person as shown below for both the JDK 8 and Guava cases

public class Person {

    private String firstName;

    private String lastName;

    private int age;

    private Optional suffix;
...
...

As shown in the above snippet the Person class has fields like firstName, lastName, age, an Optional suffix and getters and setters for these.

1.0 Predicates

A Predicate is a boolean valued function for an argument.
Now we will define Predicate in Guava and JDK 8 and show how to get the list of people whose age is over 30.

The following snippet shows how to use a Predicate which has an apply (Person input) method that takes a Person object as input and validates if the age of the person is above 30

1.1 Predicate with Guava

Here is the code showing how to use com.google.common.base.Predicate

  final List persons = Person.createList();

        final Predicate ageOver30 = new Predicate() {
            public boolean apply(Person input) {
                return input.getAge() > 30;
            }
           
        };

        Collection filteredPersons = Collections2.filter(persons,
                ageOver30);
       

The above snippet returns a Collection that satisfy that predicate ageOver30 by using Collections2.filter() method which takes a Predicate as an argument.

1.2 Predicate with JDK8

Here is a snippet of how to achieve the same behaviour using java.util.function.Predicate
The Predicate has a test method what checks for the ageOver30 Predicate

final List persons = Person.createList();

        final Predicate ageOver30 = new Predicate() {
            public boolean test(Person person) {
                return person.getAge() > 30;

            }
        };

        Stream filteredPersons = persons.stream().filter(
                ageOver30);

The above snippet transforms (List) into a Stream with the stream() method on the Collection interface. The filter() method takes the ageOver30 Predicate and returns a stream that satisfies the criteria.

2.0 Combining Predicates

Predicates can be combined with other predicates. For example in our sample we need to find a list of people
whose age is over 30 and whose name begins with "W", we can achieve this functionality with creating two
Predicates

  • ageOver30
  • nameBeginsWith

Next we combine the 2 predicates by calling the and method with these two predicates.

2.1 Combining Predicates with Guava

Here is a code snippet with Guava predicate class which defines 2 predicates ageOver30 and nameBeginsWith

        final List persons = Person.createList();

        final Predicate ageOver30 = new Predicate() {
            public boolean apply(Person input) {
                return input.getAge() > 30;
            }

        };
        final Predicate nameBeginsWith = new Predicate() {
            public boolean apply(Person person) {
                return person.getLastName().startsWith("W");

            }
        };

        Collection filteredPersons = Collections2.filter(persons,
                Predicates.and(ageOver30, nameBeginsWith));

The above snippet returns a filtered list from the Collections2.filter() method by passing the combined predicates Predicates.and(ageOver30,nameBeginsWith)

2.2 Combining Predicates with JDK 8

Here is the same functionality using java.util.function.Predicate.and/or/negate

 public Stream getMultiplePredicates() {
        final List persons = Person.createList();

        final Predicate ageOver30 = new Predicate() {
            public boolean test(Person person) {
                return person.getAge() > 30;

            }
        };
        final Predicate nameBeginsWith = new Predicate() {
            public boolean test(Person person) {
                return person.getLastName().startsWith("W") ;

            }
        };

        Stream filteredPersons = persons.stream().filter(
                ageOver30.and(nameBeginsWith));
        return filteredPersons;
    }

The above snippet returns a stream by filtering the combined ageOver30.and(nameBeginsWith)) predicates.

3.0 Supplier

Supplier is a functional interface that encapsulates an operation and allows lazy evaluation of the operation. It supplies objects of a particular type.

3.1 Supplier in Guava

Here is a snippet of how to use com.google.common.base.Supplier in Guava

public int getSupplier() {
        Supplier person = new Supplier() {
            public Person get() {
                return new Person("James", "Sculley", 53,Optional.of("Sr"));
            }
        };

        return person.get().getAge();
    }

As seen in the above snippet we create a new Supplier and the get() method returns a new instance of Person.

3.2 Supplier in JDK 8

The following code shows how to create a java.util.function.Supplier with Lamda expressions in JDK 8.

public int getSupplier() {
        final List persons = Person.createList();
        Supplier anotherone = () -> { Person psn = new Person("James", "Sculley", 53, Optional.of("Sr"));
            return psn;
        };

        return anotherone.get().getAge();
    }

As shown in above snippet, similar to the Guava case, we create a new Supplier and the get() method returns a new instance of Person.

4.0 Joiner/StringJoiner

A Joiner in Guava/ StringJoiner in JDK8 joins text together separated by delimiters.

4.1 Joiner in Guava

Here is an example of a Joiner in Guava which joins the various string delimited by ';'

    public String getJoiner() {
        Joiner joiner = Joiner.on("; ");
        return joiner.join("Violet", "Indigo", "Blue", "Green", "Yellow", "Orange", "Red");
    }

4.2 StringJoiner in JDK 8

The following snippet shows how the equivalent functionality in JDK 8 is:

    public String getJoiner() {
        StringJoiner joiner = new StringJoiner("; ");
        return joiner.add("Violet").add( "Indigo").add( "Blue").add( "Green")
        .add("Yellow").add( "Orange").add( "Red").toString();
    }

5.0 java.util.Optional

java.util.Optional is a way for programmers to indicate that there may have been a value initially, that is now set to null or no value was ever found.

5.1 Optional in Guava

Here is a sample of com.google.common.base.Optional

  • Optional.of(T) :Make an Optional containing the given non-null value, or fail fast on null.
  • Optional.absent(): Return an absent Optional of some type.
  • Optional.fromNullable(T): Turn the given possibly-null reference into an Optional, treating non-null as present and null as absent.

Here is the code which declares the suffix of a Person as Optional

Optional suffix = Optional.of("Sr")

5.2 Optional in JDK8

  • Optional.of(T); Returns an Optional with the specified present non-null value.
  • Optional.ofNullable(T);Returns an Optional describing the specified value, if non-null, otherwise returns an empty Optional
  • Optional.empty(); Returns an empty Optional instance. No value is present for this Optional.

Here is the code which declares the suffix of a Person as Optional

Optional suffix = Optional.of("Sr")

6.0 SettableFuture in Guava/ CompletableFuture in JDK 8

These extend the Future and provide asynchronous, event-driven programming model in contrast to the blocking nature of Future in java.

SettableFuture is similar to CompletableFuture in JDK 8 which can help to create a Future object for an event or a task which will occur. Code calling future.get() will block forever. When the asynchronous task finishes execution it calls future.set(). Now all the code blocking on Future.get() will get the details.

6.1 SettableFuture in Guava

Here is a simple case demonstrating this functionality in Guava and JDK8

public SettableFuture getSettableFuture() {
        final SettableFuture future = SettableFuture.create();
        return future;
    }

    public void handleFutureTask(SettableFuture sf) throws InterruptedException {
        Thread.sleep(5000);
        sf.set("Test");
    }

In the above snippet we create a new SettableFuture in default state using SettableFuture.create(). The set() method sets the value for this future object.

6.2 CompletableFuture in JDK8

The following code shows how the equivalent functionality is achieved with CompletableFuture in JDK 8.

public CompletableFuture getCompletableFuture() {
        final CompletableFuture future = new CompletableFuture<>();
        return future;
    }

    public void handleFutureTask(CompletableFuture cf) throws InterruptedException {
        Thread.sleep(5000);
        cf.complete("Test");
    }

As shown in the above snippet we create a CompletableFuture and invoke the complete method to set the value for this future object.

The above samples showed how JDK 8 standardizes in the platform and augments to some of the functionality with Guava library aimed to provide with JDK7. JDK 8 has been a great leap in terms of the newer capabilities it provided. Guava will definitely provide additional improvements using the standardized API.