Backend Development 18 min read

Unlock Java Efficiency: Master Guava’s Most Powerful Features

This article introduces the essential Guava utilities for Java developers, covering data validation, immutable collections, collection factories, multiset and multimap handling, advanced string operations, and simple caching, all with clear code examples to make your code more elegant and robust.

macrozheng
macrozheng
macrozheng
Unlock Java Efficiency: Master Guava’s Most Powerful Features

Guava is Google’s open‑source core library for Java, offering utilities such as data validation, immutable collections, collection factories, multiset, multimap, string handling, and caching.

Recently I noticed a colleague’s code heavily using Guava, which made the code much cleaner, so I share the most useful Guava features.

Data Validation

Guava provides concise methods for null checks and argument validation.

Non‑null check

<code><!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>30.0-jre</version>
</dependency></code>
<code>String param = "未读代码";
String name = Preconditions.checkNotNull(param);
System.out.println(name); // 未读代码
String param2 = null;
String name2 = Preconditions.checkNotNull(param2); // NullPointerException
System.out.println(name2);
</code>

You can also provide a custom error message:

<code>String param2 = null;
String name2 = Preconditions.checkNotNull(param2, "param2 is null");
// java.lang.NullPointerException: param2 is null
</code>

Argument validation works similarly:

<code>String param = "www.github.com2";
String wdbyte = "www.github.com";
Preconditions.checkArgument(wdbyte.equals(param), "[%s] 404 NOT FOUND", param);
// java.lang.IllegalArgumentException: [www.github.com2] 404 NOT FOUND
</code>

Guava can also check collection indexes:

<code>List<String> list = Lists.newArrayList("a", "b", "c", "d");
int index = Preconditions.checkElementIndex(5, list.size());
// java.lang.IndexOutOfBoundsException: index (5) must be less than size (4)
</code>

Immutable Collections

Immutable collections cannot be modified after creation, offering thread safety, memory efficiency, and safe sharing.

Thread‑safe because elements cannot change.

Safe to expose to third‑party code.

Potentially lower memory usage.

Useful as constant collections.

Creation methods

<code>ImmutableSet<String> immutableSet = ImmutableSet.of("a", "b", "c");
immutableSet.forEach(System.out::println);
// a
// b
// c

ImmutableSet<String> immutableSet2 = ImmutableSet.<String>builder()
    .add("hello")
    .add(new String("未读代码"))
    .build();
immutableSet2.forEach(System.out::println);
// hello
// 未读代码

ArrayList<String> arrayList = new ArrayList();
arrayList.add("www.github.com");
arrayList.add("https");
ImmutableSet<String> immutableSet3 = ImmutableSet.copyOf(arrayList);
immutableSet3.forEach(System.out::println);
// www.github.com
// https
</code>

Attempting to modify an immutable collection throws

UnsupportedOperationException

.

<code>ArrayList<String> arrayList = new ArrayList();
arrayList.add("www.github.com");
arrayList.add("https");
List<String> list = Collections.unmodifiableList(arrayList);
list.forEach(System.out::println); // www.github.com https
list.add("未读代码"); // java.lang.UnsupportedOperationException
</code>

Collection Factory Methods

Guava provides convenient factory methods for creating and populating collections.

Creating collections

<code>List<String> list1 = Lists.newArrayList();
List<String> list2 = Lists.newArrayList("a", "b", "c");
List<String> list3 = Lists.newArrayListWithCapacity(10);
LinkedList<String> linkedList1 = Lists.newLinkedList();
CopyOnWriteArrayList<String> cowArrayList = Lists.newCopyOnWriteArrayList();

HashMap<Object, Object> hashMap = Maps.newHashMap();
ConcurrentMap<Object, Object> concurrentMap = Maps.newConcurrentMap();
TreeMap<Comparable, Object> treeMap = Maps.newTreeMap();

HashSet<Object> hashSet = Sets.newHashSet();
HashSet<String> newHashSet = Sets.newHashSet("a", "a", "b", "c");
</code>

Set operations

<code>Set<String> newHashSet1 = Sets.newHashSet("a", "a", "b", "c");
Set<String> newHashSet2 = Sets.newHashSet("b", "b", "c", "d");

SetView<String> intersectionSet = Sets.intersection(newHashSet1, newHashSet2);
System.out.println(intersectionSet); // [b, c]

SetView<String> unionSet = Sets.union(newHashSet1, newHashSet2);
System.out.println(unionSet); // [a, b, c, d]

SetView<String> setView = Sets.difference(newHashSet1, newHashSet2);
System.out.println(setView); // [a]
</code>

Multiset and Multimap

Guava’s

HashMultiset

counts element occurrences efficiently.

<code>ArrayList<String> arrayList = Lists.newArrayList("a", "b", "c", "d", "a", "c");
HashMultiset<String> multiset = HashMultiset.create(arrayList);
multiset.elementSet().forEach(s -> System.out.println(s + ":" + multiset.count(s)));
/*
 a:2
 b:1
 c:2
 d:1
*/
</code>

For one‑to‑many mappings,

HashMultimap

simplifies code:

<code>HashMultimap<String, String> multimap = HashMultimap.create();
multimap.put("狗", "大黄");
multimap.put("狗", "旺财");
multimap.put("猫", "加菲");
multimap.put("猫", "汤姆");
System.out.println(multimap.get("猫")); // [加菲, 汤姆]
</code>

String Operations

Joining strings

<code>ArrayList<String> list = Lists.newArrayList("a", "b", "c", null);
String join = Joiner.on(",").skipNulls().join(list);
System.out.println(join); // a,b,c

String join1 = Joiner.on(",").useForNull("空值").join("旺财", "汤姆", "杰瑞", null);
System.out.println(join1); // 旺财,汤姆,杰瑞,空值
</code>

Splitting strings

<code>String str = ",a , ,b ,";
Iterable<String> split = Splitter.on(",")
    .omitEmptyStrings()
    .trimResults()
    .split(str);
split.forEach(System.out::println);
// a
// b
</code>

Cache

Guava provides a lightweight cache with size limits and expiration.

<code>CacheLoader<String, Animal> cacheLoader = new CacheLoader<String, Animal>() {
    @Override
    public Animal load(String s) {
        return null;
    }
};
LoadingCache<String, Animal> loadingCache = CacheBuilder.newBuilder()
    .maximumSize(1000)
    .expireAfterWrite(3, TimeUnit.SECONDS)
    .removalListener(new MyRemovalListener())
    .build(cacheLoader);

loadingCache.put("狗", new Animal("旺财", 1));
loadingCache.put("猫", new Animal("汤姆", 3));
loadingCache.put("狼", new Animal("灰太狼", 4));

loadingCache.invalidate("猫");
Animal animal = loadingCache.get("狼");
System.out.println(animal);
Thread.sleep(4 * 1000);
System.out.println(loadingCache.get("狼")); // triggers expiration

class MyRemovalListener implements RemovalListener<String, Animal> {
    @Override
    public void onRemoval(RemovalNotification<String, Animal> notification) {
        String reason = String.format("key=%s,value=%s,reason=%s",
            notification.getKey(), notification.getValue(), notification.getCause());
        System.out.println(reason);
    }
}

class Animal {
    private String name;
    private Integer age;
    @Override
    public String toString() {
        return "Animal{" + "name='" + name + '\'' + ", age=" + age + '}';
    }
    public Animal(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}
</code>

Conclusion

Guava offers a rich set of utilities that simplify common Java development tasks, improve code readability, and enhance performance. Integrating Guava into any Java project can make your code more elegant and maintainable.

JavacachingGuavaCollectionsimmutabilitystring-manipulationmultimap
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.