Comprehensive Java library providing essential utilities, immutable collections, caching, and concurrency tools for modern Java development.
—
Thread-safe, high-performance immutable data structures that can be safely shared between threads and cached without defensive copying. All immutable collections are inherently thread-safe and provide strong guarantees about their contents never changing.
Immutable ordered collection that maintains insertion order and allows duplicate elements.
import com.google.common.collect.ImmutableList;
// Creating immutable lists
ImmutableList<String> empty = ImmutableList.of();
ImmutableList<String> single = ImmutableList.of("single");
ImmutableList<String> multiple = ImmutableList.of("a", "b", "c", "d");
// From existing collections
List<String> mutableList = Arrays.asList("x", "y", "z");
ImmutableList<String> fromCollection = ImmutableList.copyOf(mutableList);
ImmutableList<String> fromIterator = ImmutableList.copyOf(iterator);
// Using builder for dynamic construction
ImmutableList<String> built = ImmutableList.<String>builder()
.add("first")
.add("second", "third")
.addAll(Arrays.asList("fourth", "fifth"))
.build();
// List operations (returns new immutable instances)
ImmutableList<String> reversed = list.reverse();
ImmutableList<String> subList = list.subList(1, 3);
// Element access
String first = list.get(0);
int index = list.indexOf("b"); // -1 if not found
int lastIndex = list.lastIndexOf("b");
// Conversion
List<String> mutableCopy = list.asList(); // Returns the same instance (already a List)
String[] array = list.toArray(new String[0]);
// Iteration maintains order
for (String item : list) {
System.out.println(item);
}Key Features:
Immutable unordered collection with unique elements, optimized for containment checks.
import com.google.common.collect.ImmutableSet;
// Creating immutable sets
ImmutableSet<String> empty = ImmutableSet.of();
ImmutableSet<String> single = ImmutableSet.of("unique");
ImmutableSet<String> multiple = ImmutableSet.of("a", "b", "c");
// From collections (automatically removes duplicates)
Set<String> mutableSet = new HashSet<>(Arrays.asList("x", "y", "z", "x"));
ImmutableSet<String> fromCollection = ImmutableSet.copyOf(mutableSet); // {x, y, z}
// Using builder
ImmutableSet<String> built = ImmutableSet.<String>builder()
.add("alpha")
.add("beta")
.addAll(Arrays.asList("gamma", "delta"))
.add("alpha") // Duplicates ignored
.build();
// Set operations (return new immutable instances)
ImmutableSet<String> union = set1.union(set2);
ImmutableSet<String> intersection = set1.intersection(set2);
// Containment (optimized performance)
boolean contains = set.contains("item"); // O(1) average case
boolean containsAll = set.containsAll(Arrays.asList("a", "b"));
// Conversion
Set<String> mutableCopy = new HashSet<>(set);
List<String> asList = set.asList(); // Arbitrary orderImmutable set with elements maintained in sorted order according to their natural ordering or a provided comparator.
import com.google.common.collect.ImmutableSortedSet;
import java.util.Comparator;
// Natural ordering
ImmutableSortedSet<String> natural = ImmutableSortedSet.of("c", "a", "b"); // Stored as [a, b, c]
ImmutableSortedSet<Integer> numbers = ImmutableSortedSet.of(5, 1, 3, 2); // [1, 2, 3, 5]
// Custom comparator
ImmutableSortedSet<String> byLength = ImmutableSortedSet.orderedBy(
Comparator.comparing(String::length).thenComparing(Comparator.naturalOrder())
).add("apple").add("pie").add("a").build(); // [a, pie, apple]
// Builders for different orderings
ImmutableSortedSet<String> naturalOrder = ImmutableSortedSet.<String>naturalOrder()
.add("zebra")
.add("apple")
.add("banana")
.build(); // [apple, banana, zebra]
ImmutableSortedSet<String> reverseOrder = ImmutableSortedSet.<String>reverseOrder()
.addAll(Arrays.asList("a", "b", "c"))
.build(); // [c, b, a]
// Range operations (leveraging sorted order)
ImmutableSortedSet<Integer> range = ImmutableSortedSet.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
ImmutableSortedSet<Integer> headSet = range.headSet(5); // [1, 2, 3, 4]
ImmutableSortedSet<Integer> tailSet = range.tailSet(7); // [7, 8, 9, 10]
ImmutableSortedSet<Integer> subSet = range.subSet(3, 8); // [3, 4, 5, 6, 7]
// First/Last access (O(1))
Integer first = range.first(); // 1
Integer last = range.last(); // 10
// Floor/Ceiling operations
Integer floor = range.floor(4); // 4 (largest element ≤ 4)
Integer ceiling = range.ceiling(4); // 4 (smallest element ≥ 4)
Integer lower = range.lower(4); // 3 (largest element < 4)
Integer higher = range.higher(4); // 5 (smallest element > 4)Immutable key-value mapping with unique keys, optimized for lookups.
import com.google.common.collect.ImmutableMap;
// Creating immutable maps
ImmutableMap<String, Integer> empty = ImmutableMap.of();
ImmutableMap<String, Integer> single = ImmutableMap.of("key", 42);
ImmutableMap<String, Integer> multiple = ImmutableMap.of(
"one", 1,
"two", 2,
"three", 3
);
// From existing maps
Map<String, Integer> mutableMap = new HashMap<>();
mutableMap.put("x", 24);
mutableMap.put("y", 25);
ImmutableMap<String, Integer> fromMap = ImmutableMap.copyOf(mutableMap);
// Using builder for larger maps
ImmutableMap<String, String> built = ImmutableMap.<String, String>builder()
.put("CA", "California")
.put("NY", "New York")
.putAll(existingStateMap)
.build();
// Builder with expected size for performance
ImmutableMap<Integer, String> withCapacity = ImmutableMap.<Integer, String>builderWithExpectedSize(100)
.put(1, "first")
.put(2, "second")
.build();
// Map operations
Integer value = map.get("key"); // null if not present
Integer valueWithDefault = map.getOrDefault("missing", 0);
boolean hasKey = map.containsKey("key");
boolean hasValue = map.containsValue(42);
// Views (all immutable)
ImmutableSet<String> keys = map.keySet();
ImmutableCollection<Integer> values = map.values();
ImmutableSet<Map.Entry<String, Integer>> entries = map.entrySet();
// Iteration maintains insertion order (in most implementations)
for (Map.Entry<String, Integer> entry : map.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue();
}Immutable map with keys maintained in sorted order, enabling efficient range operations.
import com.google.common.collect.ImmutableSortedMap;
// Natural key ordering
ImmutableSortedMap<String, Integer> natural = ImmutableSortedMap.of(
"zebra", 26,
"apple", 1,
"banana", 2
); // Keys stored as: [apple, banana, zebra]
// Custom comparator for keys
ImmutableSortedMap<String, String> byLength = ImmutableSortedMap.<String, String>orderedBy(
Comparator.comparing(String::length).thenComparing(Comparator.naturalOrder())
)
.put("a", "short")
.put("medium", "middle")
.put("z", "also short")
.build(); // Keys: [a, z, medium]
// Builders with different orderings
ImmutableSortedMap<Integer, String> ascending = ImmutableSortedMap.<Integer, String>naturalOrder()
.put(3, "three")
.put(1, "one")
.put(2, "two")
.build(); // Keys: [1, 2, 3]
ImmutableSortedMap<String, Integer> descending = ImmutableSortedMap.<String, Integer>reverseOrder()
.put("a", 1)
.put("c", 3)
.put("b", 2)
.build(); // Keys: [c, b, a]
// Range operations on keys
ImmutableSortedMap<Integer, String> numbers = ImmutableSortedMap.of(
1, "one", 3, "three", 5, "five", 7, "seven", 9, "nine"
);
ImmutableSortedMap<Integer, String> headMap = numbers.headMap(5); // {1=one, 3=three}
ImmutableSortedMap<Integer, String> tailMap = numbers.tailMap(5); // {5=five, 7=seven, 9=nine}
ImmutableSortedMap<Integer, String> subMap = numbers.subMap(3, 8); // {3=three, 5=five, 7=seven}
// Key navigation
Integer firstKey = numbers.firstKey(); // 1
Integer lastKey = numbers.lastKey(); // 9
String firstValue = numbers.values().iterator().next(); // "one"Immutable collection that allows duplicate elements and tracks count of each element.
import com.google.common.collect.ImmutableMultiset;
// Creating immutable multisets
ImmutableMultiset<String> empty = ImmutableMultiset.of();
ImmutableMultiset<String> single = ImmutableMultiset.of("apple");
ImmutableMultiset<String> multiple = ImmutableMultiset.of("apple", "banana", "apple", "cherry");
// From collections (preserves counts)
List<String> fruits = Arrays.asList("apple", "apple", "banana", "apple");
ImmutableMultiset<String> fromCollection = ImmutableMultiset.copyOf(fruits);
// Using builder with counts
ImmutableMultiset<String> built = ImmutableMultiset.<String>builder()
.add("apple")
.addCopies("banana", 3)
.add("cherry", "cherry")
.setCount("orange", 2)
.build();
// Count operations
int appleCount = multiset.count("apple"); // Number of occurrences
int totalSize = multiset.size(); // Total elements including duplicates
int distinctSize = multiset.elementSet().size(); // Number of unique elements
// Views
ImmutableSet<String> elements = multiset.elementSet(); // Unique elements
ImmutableSet<Multiset.Entry<String>> entries = multiset.entrySet(); // Element-count pairs
// Iteration over unique elements with counts
for (Multiset.Entry<String> entry : multiset.entrySet()) {
String element = entry.getElement();
int count = entry.getCount();
System.out.println(element + " appears " + count + " times");
}
// Converting to other immutable collections
ImmutableList<String> allElements = multiset.asList(); // All elements including duplicates
ImmutableSortedMultiset<String> sorted = ImmutableSortedMultiset.copyOf(multiset);Immutable multiset with elements maintained in sorted order.
import com.google.common.collect.ImmutableSortedMultiset;
// Natural ordering
ImmutableSortedMultiset<String> natural = ImmutableSortedMultiset.of(
"zebra", "apple", "banana", "apple"
); // Elements: [apple (×2), banana, zebra]
// Custom comparator
ImmutableSortedMultiset<String> byLength = ImmutableSortedMultiset.<String>orderedBy(
Comparator.comparing(String::length).thenComparing(Comparator.naturalOrder())
)
.addCopies("a", 3)
.addCopies("apple", 2)
.add("pie")
.build(); // Elements by length: [a (×3), pie, apple (×2)]
// Range operations
ImmutableSortedMultiset<Integer> numbers = ImmutableSortedMultiset.of(1, 1, 2, 3, 3, 3, 4, 5);
ImmutableSortedMultiset<Integer> headMultiset = numbers.headMultiset(3, BoundType.CLOSED); // [1 (×2), 2, 3 (×3)]
ImmutableSortedMultiset<Integer> tailMultiset = numbers.tailMultiset(3, BoundType.OPEN); // [4, 5]
// First/Last operations
Multiset.Entry<Integer> firstEntry = numbers.firstEntry(); // 1 (count: 2)
Multiset.Entry<Integer> lastEntry = numbers.lastEntry(); // 5 (count: 1)Immutable mapping from keys to multiple values, combining the benefits of multimaps with immutability.
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableSetMultimap;
// Creating immutable multimaps
ImmutableMultimap<String, String> empty = ImmutableMultimap.of();
ImmutableMultimap<String, String> single = ImmutableMultimap.of("key", "value");
ImmutableMultimap<String, String> multiple = ImmutableMultimap.of(
"fruits", "apple",
"fruits", "banana",
"colors", "red"
);
// From existing multimaps
ListMultimap<String, String> mutable = ArrayListMultimap.create();
mutable.put("a", "1");
mutable.put("a", "2");
ImmutableMultimap<String, String> fromMultimap = ImmutableMultimap.copyOf(mutable);
// Using builders
ImmutableListMultimap<String, Integer> listMultimap = ImmutableListMultimap.<String, Integer>builder()
.put("even", 2)
.put("even", 4)
.put("even", 6)
.put("odd", 1)
.putAll("odd", Arrays.asList(3, 5))
.build();
ImmutableSetMultimap<String, String> setMultimap = ImmutableSetMultimap.<String, String>builder()
.put("vowels", "a")
.put("vowels", "e")
.put("vowels", "a") // Duplicate ignored in SetMultimap
.build();
// Access operations
ImmutableCollection<String> fruits = multimap.get("fruits"); // All values for key
boolean hasKey = multimap.containsKey("fruits");
boolean hasEntry = multimap.containsEntry("fruits", "apple");
boolean hasValue = multimap.containsValue("apple");
// Views (all immutable)
ImmutableSet<String> keys = multimap.keySet();
ImmutableCollection<String> values = multimap.values();
ImmutableCollection<Map.Entry<String, String>> entries = multimap.entries();
ImmutableMap<String, Collection<String>> asMap = multimap.asMap();
// Inverse operation (for certain multimap types)
ImmutableMultimap<String, String> inverse = multimap.inverse();Immutable two-dimensional table structure for row-column-value mappings.
import com.google.common.collect.ImmutableTable;
// Creating immutable tables
ImmutableTable<String, String, Integer> empty = ImmutableTable.of();
ImmutableTable<String, String, Integer> single = ImmutableTable.of("row", "col", 42);
// Using builder for multiple entries
ImmutableTable<String, String, Integer> grades = ImmutableTable.<String, String, Integer>builder()
.put("Alice", "Math", 95)
.put("Alice", "Science", 87)
.put("Bob", "Math", 82)
.put("Bob", "Science", 91)
.build();
// From existing tables
Table<String, String, Integer> mutable = HashBasedTable.create();
mutable.put("x", "y", 1);
ImmutableTable<String, String, Integer> fromTable = ImmutableTable.copyOf(mutable);
// Access operations
Integer grade = grades.get("Alice", "Math"); // 95, null if not present
boolean hasEntry = grades.contains("Alice", "Math");
boolean hasRow = grades.containsRow("Alice");
boolean hasColumn = grades.containsColumn("Math");
// Row and column views (all immutable)
ImmutableMap<String, Integer> aliceGrades = grades.row("Alice"); // {Math=95, Science=87}
ImmutableMap<String, Integer> mathGrades = grades.column("Math"); // {Alice=95, Bob=82}
// All views
ImmutableSet<String> students = grades.rowKeySet(); // [Alice, Bob]
ImmutableSet<String> subjects = grades.columnKeySet(); // [Math, Science]
ImmutableCollection<Integer> allGrades = grades.values(); // [95, 87, 82, 91]
ImmutableSet<Table.Cell<String, String, Integer>> cells = grades.cellSet();
// Size
int totalEntries = grades.size(); // 4
boolean isEmpty = grades.isEmpty();All immutable collections are inherently thread-safe:
// Good: Public API return values
public ImmutableList<String> getNames() {
return names; // Safe to return directly, no defensive copying needed
}
// Good: Configuration and constants
public static final ImmutableMap<String, String> CONFIG = ImmutableMap.of(
"host", "localhost",
"port", "8080"
);
// Good: Builder pattern for optional parameters
public class Configuration {
private final ImmutableSet<String> enabledFeatures;
private Configuration(Builder builder) {
this.enabledFeatures = builder.featuresBuilder.build();
}
public static class Builder {
private final ImmutableSet.Builder<String> featuresBuilder = ImmutableSet.builder();
public Builder addFeature(String feature) {
featuresBuilder.add(feature);
return this;
}
public Configuration build() {
return new Configuration(this);
}
}
}// Efficient building of large collections
ImmutableList.Builder<String> listBuilder = ImmutableList.builderWithExpectedSize(1000);
for (String item : largeDataSet) {
if (shouldInclude(item)) {
listBuilder.add(process(item));
}
}
ImmutableList<String> result = listBuilder.build();
// Combining builders with other operations
ImmutableSet.Builder<String> setBuilder = ImmutableSet.builder();
setBuilder.addAll(existingCollection);
setBuilder.add("additional", "items");
ImmutableSet<String> combined = setBuilder.build();// Before: Mutable with defensive copying
public List<String> getItems() {
return new ArrayList<>(this.items); // Expensive defensive copy
}
public void setItems(List<String> items) {
this.items = new ArrayList<>(items); // Another defensive copy
}
// After: Immutable without copying
public ImmutableList<String> getItems() {
return this.items; // No copying needed, safe to return directly
}
public void setItems(Collection<String> items) {
this.items = ImmutableList.copyOf(items); // Copy once, then immutable
}Immutable collections provide a powerful foundation for building thread-safe, efficient applications while eliminating common sources of bugs related to unintended mutation and concurrent access.
Install with Tessl CLI
npx tessl i tessl/maven-com-google-guava--guava