# Core Guava Collections: Immutable, Mutable, and Special-Purpose Types Explained

> Explore Google Guava's core collections including immutable, mutable, and special-purpose types like Multimap and BiMap to enhance your Java development.

- Repository: [Google/guava](https://github.com/google/guava)
- Tags: deep-dive
- Published: 2026-08-10

---

**Google Guava provides three families of core collections—immutable snapshots, enhanced mutable implementations, and special-purpose structures like Multimap, BiMap, and Table—that extend the JDK's standard library.**

Google Guava's `com.google.common.collect` package enhances Java's standard collections framework with production-ready data structures designed for thread safety, performance, and expressiveness. These core Guava collections fall into three architectural families: immutable read-only types, mutable drop-in replacements with extra functionality, and specialized structures that have no direct JDK equivalent. Understanding these categories helps developers choose the right tool for everything from defensive copying to complex interval-based data modeling.

## Immutable Collections: Thread-Safe Snapshots

Guava's immutable collections provide **defensive copies** that are inherently thread-safe and memory-efficient. Unlike `Collections.unmodifiableList()`, which wraps a mutable backing list, Guava's `ImmutableList`, `ImmutableSet`, and `ImmutableMap` are final classes that guarantee immutability at the API level.

### ImmutableList, ImmutableSet, and ImmutableMap

The foundation of Guava's immutable family resides in [`ImmutableList.java`](https://github.com/google/guava/blob/main/ImmutableList.java), [`ImmutableSet.java`](https://github.com/google/guava/blob/main/ImmutableSet.java), and [`ImmutableMap.java`](https://github.com/google/guava/blob/main/ImmutableMap.java). These classes use structural sharing where possible and compact internal representations to minimize overhead. As implemented in `google/guava`, they disallow null elements and provide constant-time `contains()` operations for sets.

```java
// Immutable collections – no modifications allowed after creation
ImmutableList<String> colors =
    ImmutableList.of("red", "green", "blue");

// Attempting to modify throws UnsupportedOperationException
// colors.add("yellow"); // Compilation error or runtime exception

```

### ImmutableMultimap and ImmutableTable

For complex data structures, [`ImmutableMultimap.java`](https://github.com/google/guava/blob/main/ImmutableMultimap.java) and [`ImmutableTable.java`](https://github.com/google/guava/blob/main/ImmutableTable.java) provide immutable variants of Guava's special-purpose collections. These support the builder pattern for constructing large immutable instances efficiently.

```java
// ImmutableTable – a 2‑dimensional map
ImmutableTable<String, String, Integer> grades =
    ImmutableTable.<String, String, Integer>builder()
        .put("alice", "math", 95)
        .put("bob", "history", 88)
        .build();

```

## Mutable Core Collections: Enhanced JDK Replacements

Guava offers mutable collections that serve as **drop-in replacements** for standard JDK types while adding functionality like counting duplicates or maintaining bidirectional mappings. These implementations generally provide better scalability patterns than their standard library counterparts.

### Multimap Implementations

The `Multimap` interface, defined in [`Multimap.java`](https://github.com/google/guava/blob/main/Multimap.java), represents a mapping from keys to multiple values (essentially `Map<K, Collection<V>>`). [`ArrayListMultimap.java`](https://github.com/google/guava/blob/main/ArrayListMultimap.java) provides a mutable implementation backed by `ArrayList` instances, while `HashMultimap` uses hash-based sets for values.

```java
// Mutable Multimap – a key can map to many values
ArrayListMultimap<String, Integer> scores = ArrayListMultimap.create();
scores.put("alice", 10);
scores.put("alice", 8);
scores.put("bob", 7);

// alice now maps to [10, 8]
List<Integer> aliceScores = scores.get("alice");

```

### Multiset and BiMap

[`HashMultiset.java`](https://github.com/google/guava/blob/main/HashMultiset.java) implements the `Multiset` interface (also called a "bag"), which counts element occurrences. [`HashBiMap.java`](https://github.com/google/guava/blob/main/HashBiMap.java) enforces a one-to-one relationship between keys and values, enabling inverse lookups via the `inverse()` method.

```java
// BiMap – bidirectional map
BiMap<String, Integer> idByName = HashBiMap.create();
idByName.put("alice", 1);
idByName.put("bob", 2);
int aliceId = idByName.get("alice");          // → 1
String name = idByName.inverse().get(2);      // → "bob"

```

## Special-Purpose Collections: Beyond Standard Maps

These data structures address specific use cases that standard Java collections handle poorly or not at all, including two-dimensional data and continuous interval modeling.

### Table (Two-Dimensional Maps)

The `Table` interface, defined in [`Table.java`](https://github.com/google/guava/blob/main/Table.java), provides a matrix-like structure with row and column keys (`Table<R, C, V>`). `HashBasedTable` offers a mutable implementation using nested hash maps, while `ImmutableTable` provides the immutable variant.

### RangeSet and RangeMap

`RangeSet` and `RangeMap`, backed by implementations like [`TreeRangeSet.java`](https://github.com/google/guava/blob/main/TreeRangeSet.java) and [`TreeRangeMap.java`](https://github.com/google/guava/blob/main/TreeRangeMap.java), model continuous intervals using the `Range<T>` class. These red-black tree-backed structures maintain non-overlapping ranges and support logarithmic-time operations.

```java
// RangeSet – store non‑overlapping integer intervals
RangeSet<Integer> rangeSet = TreeRangeSet.create();
rangeSet.add(Range.closed(1, 5));
rangeSet.add(Range.open(10, 20));   // {1..5} ∪ (10,20)

// Query operations
boolean contains15 = rangeSet.contains(15); // false

```

## Summary

- **Immutable collections** (`ImmutableList`, `ImmutableMap`, etc.) provide thread-safe, read-only snapshots with internal structure sharing, implemented in files like [`ImmutableList.java`](https://github.com/google/guava/blob/main/ImmutableList.java) and [`ImmutableMap.java`](https://github.com/google/guava/blob/main/ImmutableMap.java).
- **Mutable core collections** such as `ArrayListMultimap` and `HashBiMap` extend standard JDK interfaces with functionality for multiple values per key and bidirectional mappings.
- **Special-purpose types** including `Table`, `RangeSet`, and `RangeMap` (defined in [`Table.java`](https://github.com/google/guava/blob/main/Table.java), [`RangeSet.java`](https://github.com/google/guava/blob/main/RangeSet.java), and [`TreeRangeMap.java`](https://github.com/google/guava/blob/main/TreeRangeMap.java)) handle two-dimensional data and continuous intervals without custom wrapper classes.
- All Guava collections disallow null elements by default and integrate seamlessly with Java's standard collection interfaces.

## Frequently Asked Questions

### What makes Guava's immutable collections different from Collections.unmodifiableList?

Guava's immutable collections are **truly immutable** rather than merely unmodifiable views. While `Collections.unmodifiableList()` wraps a mutable list that can still be changed by other references, `ImmutableList` (as implemented in [`ImmutableList.java`](https://github.com/google/guava/blob/main/ImmutableList.java)) uses final classes and defensive copying to guarantee that no modifications are possible after construction. This makes them inherently thread-safe without synchronization and safe to use as constants or return values from APIs.

### When should I use ArrayListMultimap vs HashMultimap?

Use **ArrayListMultimap** (from [`ArrayListMultimap.java`](https://github.com/google/guava/blob/main/ArrayListMultimap.java)) when you need to preserve duplicate values for a single key or maintain insertion order, as it stores values in an `ArrayList`. Choose **HashMultimap** when you require set semantics for values—preventing duplicates per key—since it stores values in a `HashSet`. Both implement the `Multimap` interface but optimize for different access patterns and memory usage.

### How does BiMap enforce unique values?

`BiMap` maintains two internal maps to ensure a one-to-one correspondence between keys and values. When calling `put()` on `HashBiMap` (implemented in [`HashBiMap.java`](https://github.com/google/guava/blob/main/HashBiMap.java)), the method checks if the value already exists in the inverse map and removes the old key association if necessary. This constraint enables the `inverse()` method to return a view that swaps keys and values while maintaining the bidirectional mapping invariant.

### Are Guava collections compatible with Java Streams?

Yes, all Guava core collections implement standard Java collection interfaces and work seamlessly with the Stream API. `ImmutableList` and `ImmutableSet` provide stream-like builder methods, while mutable collections like `ArrayListMultimap` support `asMap()` views that can be streamed. For specialized collections, `RangeSet` offers `asRanges()` and `asDescendingSetOfRanges()` methods that return `Iterable` views suitable for streaming operations.