1. Introduction

This article is first in the series about the new features launched with Version 21 of the Google Guava library. We'll discuss newly added classes and some major changes from previous versions of Guava.

More specifically, we'll discuss additions and changes in the common.collect package.

Guava 21 introduces some new and useful functionality in the common.collect package; let's have a quick look at some of these new utilities and how we can get the most out of them.

2. Streams

We're all excited about the latest addition of java.util.stream.Stream in Java 8. Well, Guava is now making good use of streams and provides what Oracle may have missed.

Streams is a static utility class, with some much-needed utilities for handling Java 8 streams.

2.1. Streams.stream()

Streams class provides four ways to create streams using Iterable, Iterator, Optional and Collection.

Though, stream creation using Collection is deprecated, as it's provided by Java 8 out of the box:

List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Stream<Integer> streamFromCollection = Streams.stream(numbers);
Stream<Integer> streamFromIterator = Streams.stream(numbers.iterator());
Stream<Integer> streamFromIterable = Streams.stream((Iterable<Integer>) numbers);
Stream<Integer> streamFromOptional = Streams.stream(Optional.of(1));

Streams class also provides flavors with OptionalDouble, OptionalLong and OptionalInt. These methods return a stream containing only that element otherwise empty stream:

LongStream streamFromOptionalLong = Streams.stream(OptionalLong.of(1));
IntStream streamFromOptionalInt = Streams.stream(OptionalInt.of(1));
DoubleStream streamFromOptionalDouble = Streams.stream(OptionalDouble.of(1.0));

2.2. Streams.concat()

Streams class provides methods for concating more than one homogeneous streams.

Stream<Integer> concatenatedStreams = Streams.concat(streamFromCollection, streamFromIterable,streamFromIterator);

The concat functionality comes in a few flavors – LongStream, IntStream and DoubleStream.

2.3. Streams.findLast()

Streams have a utility method to find the last element in the stream by using findLast() method.

This method either returns last element or Optional.empty() if the stream is there are no elements in the stream:

List<Integer> integers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Optional<Integer> lastItem = Streams.findLast(integers.stream());

The findLast() method works for LongStream, IntStream and DoubleStream.

2.4. Streams.mapWithIndex()

By using mapWithIndex() method, each element of the stream carries information about their respective position (index):

mapWithIndex( Stream.of("a", "b", "c"), (str, index) -> str + ":" + index)

This will return Stream.of(“a:0″,”b:1″,”c:2”).

Same can be achieved with IntStream, LongStream and DoubleStream using overloaded mapWithIndex().

2.5. Streams.zip()

In order to map corresponding elements of two streams using some function, just use zip method of Streams:

  Stream.of("candy", "chocolate", "bar"),
  Stream.of("$1", "$2","$3"),
  (arg1, arg2) -> arg1 + ":" + arg2

This will return Stream.of(“candy:$1″,”chocolate:$2″,”bar:$3”);

The resulting stream will only be as long as the shorter of the two input streams; if one stream is longer, its extra element will be ignored.

3. Comparators

Guava Ordering class is deprecated and in the phase of deletion in newer versions. Most of the functionalities of Ordering class are already enlisted in JDK 8.

Guava introduces Comparators to provide additional features of Ordering which are not yet provided by the Java 8 standard libs.

Let's have a quick look at these.

3.1. Comparators.isInOrder()

This method returns true if each element in the Iterable is greater than or equal to the preceding one, as specified by the Comparator:

List<Integer> integers = Arrays.asList(1,2,3,4,4,6,7,8,9,10);
boolean isInAscendingOrder = Comparators.isInOrder(
  integers, new AscedingOrderComparator());

3.2. Comparators.isInStrictOrder()

Quite similar to the isInOrder() method but it strictly holds the condition, the element cannot be equal to the preceding one, it has to be greater than. The previous code will return false for this method.

3.3. Comparators.lexicographical()

This API returns a new Comparator instance – which sorts in lexicographical (dictionary) order comparing corresponding elements pairwise. Internally, it creates a new instance of LexicographicalOrdering().

4. MoreCollectors

MoreCollectors contains some very useful Collectors which are not present in Java 8 java.util.stream.Collectors and are not associated with com.google.common type.

Let's go over a few of these.

4.1. MoreCollectors.toOptional()

Here, Collector converts a stream containing zero or one element to an Optional:

List<Integer> numbers = Arrays.asList(1);
Optional<Integer> number = numbers.stream()
  .map(e -> e * 2)

If the stream contains more than one elements – the collector will throw *IllegalArgumentException.

4.2. MoreCollectors.onlyElement()

With this API, the Collector takes a stream containing just one element and returns the element; if the stream contains more than one element it throws IllegalArgumentException or if the stream contains zero element it throws NoSuchElementException.

5. Interners.InternerBuilder

This is an internal builder class to already existing Interners in Guava library. It provides some handy method to define concurrency level and type (weak or strong) of Interner you prefer:

Interners interners = Interners.newBuilder()

6. Conclusion

In this quick article, we explored the newly added functionality in the common.collect package of Guava 21.

The code for this article can be found on Github, as always.