Guava Collections Cookbook

1. Introduction

This cookbook article is organized into small and focused recipes and code snippets for using Guava style collections.

The format is that of a growing list of code examples with no additional explanation necessary – it is meant to keep common usages of the API easy to access during development.

2. The Recipes

downcast a List<Parent> to a List<Child>

- note: this is a workaround for non-covariant generified collections in Java

class CastFunction<F, T extends F> implements Function<F, T> {
    @Override
    public final T apply(final F from) {
        return (T) from;
    }
}
List<TypeParent> originalList = Lists.newArrayList();
List<TypeChild> theList = Lists.transform(originalList, 
    new CastFunction<TypeParent, TypeChild>());

simpler alternative without Guava – involving 2 cast operations

List<Number> originalList = Lists.newArrayList();
List<Integer> theList = (List<Integer>) (List<? extends Number>) originalList;

adding an iterable to a collection

Iterable<String> iter = Lists.newArrayList();
Collection<String> collector = Lists.newArrayList();
Iterables.addAll(collector, iter);

check if collection contains element(s) according to a custom matching rule

Iterable<String> theCollection = Lists.newArrayList("a", "bc", "def");
    boolean contains = Iterables.any(theCollection, new Predicate<String>() {
    @Override
    public boolean apply(final String input) {
        return input.length() == 1;
    }
});
assertTrue(contains);

alternative solution using search

Iterable<String> theCollection = Sets.newHashSet("a", "bc", "def");
boolean contains = Iterables.find(theCollection, new Predicate<String>() {
    @Override
    public boolean apply(final String input) {
       return input.length() == 1;
    }
}) != null;
assertTrue(contains);

alternative solution only applicable to Sets

Set<String> theCollection = Sets.newHashSet("a", "bc", "def");
boolean contains = !Sets.filter(theCollection, new Predicate<String>() {
    @Override
    public boolean apply(final String input) {
        return input.length() == 1;
    }
}).isEmpty();
assertTrue(contains);

NoSuchElementException on Iterables.find when nothing is found

Iterable<String> theCollection = Sets.newHashSet("abcd", "efgh", "ijkl");
Predicate<String> inputOfLengthOne = new Predicate<String>() {
    @Override
    public boolean apply(final String input) {
        return input.length() == 1;
    }
};
String found = Iterables.find(theCollection, inputOfLengthOne);

- this will throw the NoSuchElementException exception:

java.util.NoSuchElementException
	at com.google.common.collect.AbstractIterator.next(AbstractIterator.java:154)
	at com.google.common.collect.Iterators.find(Iterators.java:712)
	at com.google.common.collect.Iterables.find(Iterables.java:643)

- solution: there is an overloaded find method that takes the default return value as an argument and can be called with null for the desired behavior:

String found = Iterables.find(theCollection, inputOfLengthOne, null);

remove all null values from a collection

List<String> values = Lists.newArrayList("a", null, "b", "c");
Iterable<String> withoutNulls = Iterables.filter(values, Predicates.notNull());

create immutable List/Set/Map directly

ImmutableList<String> immutableList = ImmutableList.of("a", "b", "c");
ImmutableSet<String> immutableSet = ImmutableSet.of("a", "b", "c");
ImmutableMap<String, String> imuttableMap = 
    ImmutableMap.of("k1", "v1", "k2", "v2", "k3", "v3");

create immutable List/Set/Map from a standard collection

List<String> muttableList = Lists.newArrayList();
ImmutableList<String> immutableList = ImmutableList.copyOf(muttableList);

Set<String> muttableSet = Sets.newHashSet();
ImmutableSet<String> immutableSet = ImmutableSet.copyOf(muttableSet);

Map<String, String> muttableMap = Maps.newHashMap();
ImmutableMap<String, String> imuttableMap = ImmutableMap.copyOf(muttableMap);

alternative solution using builders

List<String> muttableList = Lists.newArrayList();
ImmutableList<String> immutableList = 
    ImmutableList.<String> builder().addAll(muttableList).build();

Set<String> muttableSet = Sets.newHashSet();
ImmutableSet<String> immutableSet = 
    ImmutableSet.<String> builder().addAll(muttableSet).build();

Map<String, String> muttableMap = Maps.newHashMap();
ImmutableMap<String, String> imuttableMap = 
    ImmutableMap.<String, String> builder().putAll(muttableMap).build();

3. Going Forward

As I mentioned in the beginning, I am experimenting with this different format – the cookbook – to try to gather simple common tasks of using Guava Collections in a single place. The focus of this format is simplicity and speed, so most recipes have no additional explanation other than the code example itself.

Finally – I am looking at this as a living document – I’m going to keep adding recipes and examples as I run into them. Feel free to provide more in the comments and I’ll look to incorporate them into the cookbook.

The implementation of all these examples and code snippets can be found in my Guava github project – this is an Eclipse based project, so it should be easy to import and run as it is.

I usually post about Dev stuff on Google+ - you can follow me there:

Free eBook - REST Services with Spring
Join more than 2,200 engineers!

,