Powerful Collection Utility Classes: Guava Tools Not Covered by java.util.Collections
This article explains Guava's extensive collection utility classes that complement or replace java.util.Collections, covering static factory methods, Iterable utilities, and specialized tools for Lists, Sets, Maps, Multisets, Multimaps, and Tables, with code examples illustrating their usage and advantages.
Powerful Collection Utility Classes: Guava Tools Not Covered by java.util.Collections
We summarize the relationship between collection interfaces and the corresponding utility classes in a clear way.
Collection Interface
Provided by JDK or Guava
Corresponding Guava Utility Class
Collection
JDK
Collections2
Do not confuse with java.util.Collections
List
JDK
Lists
Set
JDK
Sets
SortedSet
JDK
Sets
Map
JDK
Maps
SortedMap
JDK
Maps
Queue
JDK
Queues
Multiset
Guava
Multisets
Multimap
Guava
Multimaps
BiMap
Guava
Maps
Table
Guava
Tables
Static Factory Methods
Before JDK 7, creating a generic collection required repeating the generic type, which was cumbersome:
List<TypeThatsTooLongForItsOwnGood> list = new ArrayList<TypeThatsTooLongForItsOwnGood>();Guava provides static factory methods that infer the generic type, making code concise:
List<TypeThatsTooLongForItsOwnGood> list = Lists.newArrayList(); Map<KeyType, LongishValueType> map = Maps.newLinkedHashMap();JDK 7’s diamond operator ( <> ) eliminates this problem, but Guava’s factories offer additional flexibility, such as initializing a collection with elements or specifying an initial capacity.
Set<Type> copySet = Sets.newHashSet(elements); List<String> theseElements = Lists.newArrayList("alpha", "beta", "gamma"); List<Type> exactly100 = Lists.newArrayListWithCapacity(100); List<Type> approx100 = Lists.newArrayListWithExpectedSize(100);Iterables
Guava prefers methods that accept Iterable rather than Collection , because some data sources (e.g., database streams) cannot provide a size without materializing all elements.
Most Iterables methods have a counterpart in Iterators for working directly with Iterator s.
Since Guava 1.2, Iterables is supplemented by FluentIterable , which offers a fluent (chainable) API.
Common Methods
concat(Iterable<Iterable>)
Lazily concatenates multiple iterables
concat(Iterable...)
frequency(Iterable, Object)
Counts occurrences of an element
Comparable to Collections.frequency(Collection, Object)
partition(Iterable, int)
Partitions the iterable into fixed‑size, unmodifiable sub‑lists
Lists.partition(List, int); paddedPartition(Iterable, int)
getFirst(Iterable, T default)
Returns the first element or a default value if empty
Comparable to Iterable.iterator().next(); FluentIterable.first()
getLast(Iterable)
Returns the last element or throws
NoSuchElementExceptionif empty
getLast(Iterable, T default); FluentIterable.last()
elementsEqual(Iterable, Iterable)
True if both iterables contain equal elements in the same order
Comparable to List.equals(Object)
unmodifiableIterable(Iterable)
Returns an unmodifiable view
Comparable to Collections.unmodifiableCollection(Collection)
limit(Iterable, int)
Limits the number of elements returned
FluentIterable.limit(int)
getOnlyElement(Iterable)
Returns the sole element, failing fast if none or more than one
getOnlyElement(Iterable, T default)
Lists
Beyond static factories and functional‑style methods, Lists offers several utilities for List objects.
Method
Description
partition(List, int)
Splits the list into sub‑lists of the given size
reverse(List)
Returns a view of the list in reverse order (use
ImmutableList.reverse()for immutable lists)
List<Integer> countUp = Ints.asList(1, 2, 3, 4, 5); List<Integer> countDown = Lists.reverse(countUp); // {5,4,3,2,1} List<List<Integer>> parts = Lists.partition(countUp, 2); // {{1,2},{3,4},{5}}Sets
Sets provides a rich set of set‑theoretic operations.
Method
union(Set, Set)
intersection(Set, Set)
difference(Set, Set)
symmetricDifference(Set, Set)
Example:
Set<String> wordsWithPrimeLength = ImmutableSet.of("one", "two", "three", "six", "seven", "eight"); Set<String> primes = ImmutableSet.of("two", "three", "five", "seven"); SetView<String> intersection = Sets.intersection(primes, wordsWithPrimeLength); // contains "two", "three", "seven"
ImmutableSet<String> result = intersection.immutableCopy();Other Set Utilities
Method
Description
See Also
cartesianProduct(List<Set>)
Returns the Cartesian product of all sets
cartesianProduct(Set...)
powerSet(Set)
Returns all subsets of the given set
Set<String> animals = ImmutableSet.of("gerbil", "hamster");
Set<String> fruits = ImmutableSet.of("apple", "orange", "banana");
Set<List<String>> product = Sets.cartesianProduct(animals, fruits);
// {{"gerbil","apple"}, {"gerbil","orange"}, …}
Set<Set<String>> animalSets = Sets.powerSet(animals);
// {{}, {"gerbil"}, {"hamster"}, {"gerbil","hamster"}}Maps
Maps contains several noteworthy methods.
uniqueIndex
Maps.uniqueIndex(Iterable, Function) builds a map where the key is the value returned by the function and the value is the original element. It is useful when each element has a unique attribute.
ImmutableMap<Integer, String> stringsByLength = Maps.uniqueIndex(strings,
new Function<String, Integer>() {
public Integer apply(String s) { return s.length(); }
});If the index values are not unique, use Multimaps.index instead.
difference
Maps.difference(Map, Map) compares two maps and returns a MapDifference object with four views:
entriesInCommon() – entries present in both maps with identical values
entriesDiffering() – same keys with different values
entriesOnlyOnLeft() – entries only in the left map
entriesOnlyOnRight() – entries only in the right map
Map<String, Integer> left = ImmutableMap.of("a",1, "b",2, "c",3);
Map<String, Integer> right = ImmutableMap.of("b",2, "c",4, "d",5);
MapDifference<String,Integer> diff = Maps.difference(left, right);
// diff.entriesInCommon() -> {"b"=2}
// diff.entriesDiffering() -> {"c"=(3,4)}
// diff.entriesOnlyOnLeft() -> {"a"=1}
// diff.entriesOnlyOnRight() -> {"d"=5}BiMap Utilities
BiMap is a special map with a one‑to‑one relationship. Guava provides:
synchronizedBiMap(BiMap) – thread‑safe wrapper (similar to Collections.synchronizedMap )
unmodifiableBiMap(BiMap) – read‑only view (similar to Collections.unmodifiableMap )
Static Factory Methods for Maps
Implementation
Factory Methods
HashMap
basic, from Map, with expected size
LinkedHashMap
basic, from Map
TreeMap
basic, from Comparator, from SortedMap
EnumMap
from Class, from Map
ConcurrentMap
basic (supports all operations)
IdentityHashMap
basic
Multisets
Standard collection operations ignore element multiplicities. Multisets offers methods that respect counts.
Method
Description
Difference from Collection
containsOccurrences(Multiset sup, Multiset sub)
True if for every element o, sub.count(o) ≤ sup.count(o)
Collection.containsAll ignores multiplicities
removeOccurrences(Multiset removeFrom, Multiset toRemove)
Removes from
removeFromthe same number of occurrences as in
toRemoveCollection.removeAll removes all matching elements
retainOccurrences(Multiset removeFrom, Multiset toRetain)
Keeps at most the count of each element present in
toRetainCollection.retainAll keeps all matching elements
intersection(Multiset, Multiset)
Returns the multiset intersection
No direct Collection equivalent
Multiset<String> multiset1 = HashMultiset.create();
multiset1.add("a", 2);
Multiset<String> multiset2 = HashMultiset.create();
multiset2.add("a", 5);
boolean containsAll = multiset1.containsAll(multiset2); // true (ignores counts)
boolean containsOccurrences = Multisets.containsOccurrences(multiset1, multiset2); // false
Multisets.removeOccurrences(multiset2, multiset1); // multiset2 now has 3 "a"
multiset2.removeAll(multiset1); // removes all "a", multiset2 becomes emptyOther useful methods:
copyHighestCountFirst(Multiset) – immutable copy sorted by descending count
unmodifiableMultiset(Multiset) – read‑only view
unmodifiableSortedMultiset(SortedMultiset) – read‑only view for sorted multisets
Multiset<String> multiset = HashMultiset.create();
multiset.add("a", 3);
multiset.add("b", 5);
multiset.add("c", 1);
ImmutableMultiset<String> highest = Multisets.copyHighestCountFirst(multiset); // order: b, a, cMultimaps
Multimaps provides utilities for working with Multimap structures.
index
Similar to Maps.uniqueIndex but allows non‑unique keys. It groups elements by the value returned by a function.
ImmutableSet<String> digits = ImmutableSet.of("zero","one","two","three","four","five","six","seven","eight","nine");
Function<String,Integer> lengthFn = new Function<String,Integer>() {
public Integer apply(String s) { return s.length(); }
};
ImmutableListMultimap<Integer,String> digitsByLength = Multimaps.index(digits, lengthFn);
// Result: 3 → {"one","two","six"}, 4 → {"zero","four","five","nine"}, 5 → {"three","seven","eight"}invertFrom
Reverses a Multimap , turning values into keys. Choose the destination implementation to control ordering.
ArrayListMultimap<String,Integer> multimap = ArrayListMultimap.create();
multimap.putAll("b", Ints.asList(2,4,6));
multimap.putAll("a", Ints.asList(4,2,1));
multimap.putAll("c", Ints.asList(2,5,3));
TreeMultimap<Integer,String> inverse = Multimaps.invertFrom(multimap, TreeMultimap.create());
// inverse: 1 → {"a"}, 2 → {"a","b","c"}, 3 → {"c"}, 4 → {"a","b"}, 5 → {"c"}, 6 → {"b"}forMap
Wraps a regular Map as a SetMultimap , useful for treating a many‑to‑one map as a one‑to‑many multimap.
Map<String,Integer> map = ImmutableMap.of("a",1, "b",1, "c",2);
SetMultimap<String,Integer> multimap = Multimaps.forMap(map);
// multimap: {"a"→{1}, "b"→{1}, "c"→{2}}
Multimap<Integer,String> inverse = Multimaps.invertFrom(multimap, HashMultimap.create());
// inverse: 1→{"a","b"}, 2→{"c"}Custom Multimaps and Wrappers
Guava offers read‑only, synchronized, and custom implementations for Multimap , ListMultimap , SetMultimap , and SortedSetMultimap . Custom multimaps require a Supplier to create fresh collections for each key.
ListMultimap<String,Integer> myMultimap = Multimaps.newListMultimap(
Maps.
newTreeMap(),
new Supplier<LinkedList>() {
public LinkedList get() { return Lists.newLinkedList(); }
});Tables
Tables offers utilities for two‑dimensional map structures.
Custom Table
Tables.newCustomTable(Map, Supplier<Map>) lets you choose the map implementation for rows and columns.
// Use LinkedHashMaps for deterministic ordering
Table<String,Character,Integer> table = Tables.newCustomTable(
Maps.
>newLinkedHashMap(),
new Supplier<Map
() {
public Map
get() { return Maps.newLinkedHashMap(); }
});transpose
Tables.transpose(Table<R,C,V>) swaps rows and columns, useful for reversing a directed graph represented as a table.
Immutable and Wrapper Variants
Prefer ImmutableTable for safety. Wrapper classes include unmodifiable and synchronized versions for Table and RowSortedTable .
[Source: Concurrency Programming Network]
Qunar Tech Salon
Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.