David's Blog

Google Guava A Comprehensive Guide for Java Developers

By David Li on 2023-07-24T12:49:13.000Z

Google Guava: A Comprehensive Guide for Java Developers

Google Guava is a powerful, open-source Java library developed by Google that provides an array of utility methods and classes. It enhances the Java programming language by offering a more extensive and efficient API for tasks like collections, caching, functional programming, primitives support, and concurrency. This article will explore the key features of Guava and provide code samples to help Java developers better understand its benefits.

Table of Contents

  1. What is Google Guava?
  2. Guava Collections
  3. Immutable Collections
  4. Multimap, BiMap, and Table
  5. Caching
  6. Functional Programming
  7. Concurrency Utilities
  8. Conclusion

What is Google Guava?

Google Guava is a versatile Java library that provides a wealth of features to simplify and streamline common programming tasks. It offers a better alternative to using standard Java libraries, making code more readable, efficient, and less prone to errors. The library is used extensively by Google in many of its projects and is regarded as a reliable and well-maintained library.

Guava Collections

Guava extends the Java Collections Framework by providing additional collection types and utility methods. Some of these enhancements include:

Lists

Guava provides a Lists utility class to create and manipulate lists. For example, the Lists.newArrayList method creates a new ArrayList with the given elements:

import com.google.common.collect.Lists;

List<String> names = Lists.newArrayList("Alice", "Bob", "Charlie");

Sets

Similarly, the Sets utility class offers methods for creating and manipulating sets. The Sets.newHashSet method creates a new HashSet with the given elements:

import com.google.common.collect.Sets;

Set<String> names = Sets.newHashSet("Alice", "Bob", "Charlie");

Immutable Collections

Immutable collections are collections that cannot be modified after they are created. They are thread-safe and more efficient than their mutable counterparts. Guava provides immutable versions of lists, sets, and maps.

import com.google.common.collect.ImmutableList;

ImmutableList<String> names = ImmutableList.of("Alice", "Bob", "Charlie");

Multimap, BiMap, and Table

Guava introduces new collection types like Multimap, BiMap, and Table which address specific use cases:

Multimap

A Multimap is a map where each key can have multiple values. Guava provides several implementations, such as ArrayListMultimap and HashMultimap.

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;

Multimap<String, String> multimap = ArrayListMultimap.create();
multimap.put("Fruits", "Apple");
multimap.put("Fruits", "Banana");
multimap.put("Vegetables", "Carrot");

BiMap

A BiMap is a bidirectional map that maintains an inverse view of itself, allowing developers to quickly look up keys based on values and vice versa.

import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;

BiMap<String, Integer> biMap = HashBiMap.create();
biMap.put("One", 1);
biMap.put("Two", 2);

// Get the key for value 2
String key = biMap.inverse().get(2);  // key = "Two"

Table

A Table represents a two-dimensional map, where each cell has a row key, a column key, and a value.

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;

Table<String, String, Integer> table = HashBasedTable.create();
table.put("Alice", "Math", 90);
table.put("Alice", "Science", 85);
table.put("Bob", "Math", 80);
table.put("Bob", "Science", 75);

Caching

Guava provides a Cache interface for in-memory caching with a flexible and powerful implementation called LoadingCache. It supports features like automatic loading, eviction, and time-based expiration.

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

LoadingCache<String, String> cache = CacheBuilder.newBuilder()
    .maximumSize(100)
    .expireAfterAccess(5, TimeUnit.MINUTES)
    .build(new CacheLoader<String, String>() {
        @Override
        public String load(String key) {
            return fetchDataFromSource(key);
        }
    });

Functional Programming

Guava offers limited support for functional programming,including transformations and filtering on collections using Function and Predicate interfaces:

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;

List<String> names = Lists.newArrayList("Alice", "Bob", "Charlie");

// Define a function to convert names to uppercase
Function<String, String> toUpperCase = new Function<String, String>() {
    @Override
    public String apply(String input) {
        return input.toUpperCase();
    }
};

// Transform a list of names to uppercase
Collection<String> upperCaseNames = Collections2.transform(names, toUpperCase);

// Define a predicate to filter names starting with 'A'
Predicate<String> startsWithA = new Predicate<String>() {
    @Override
    public boolean apply(String input) {
        return input.startsWith("A");
    }
};

// Filter names starting with 'A'
Collection<String> filteredNames = Collections2.filter(names, startsWithA);

However, Java 8 introduced streams and lambda expressions, which are more powerful tools for functional programming. As a result, Guava’s functional programming features are now considered obsolete and not recommended for new projects.

Concurrency Utilities

Guava provides concurrency utilities that simplify working with threads, such as ListenableFuture and Service:

ListenableFuture

A ListenableFuture extends the standard Future interface and allows developers to register callbacks to be executed when the future completes.

import com.google.common.util.concurrent.*;

public class Example {
    public static void main(String[] args) {
        // Create an executor for the future
        ListeningExecutorService executor = MoreExecutors.listeningDecorator(
            Executors.newSingleThreadExecutor());

        // Submit a task to the executor
        ListenableFuture<String> future = executor.submit(new Callable<String>() {
            @Override
            public String call() {
                return fetchDataFromSource();
            }
        });

        // Add a callback to be executed when the future completes
        Futures.addCallback(future, new FutureCallback<String>() {
            @Override
            public void onSuccess(String result) {
                System.out.println("Data fetched: " + result);
            }

            @Override
            public void onFailure(Throwable t) {
                System.err.println("Failed to fetch data: " + t.getMessage());
            }
        }, MoreExecutors.directExecutor());
    }
}

Service

The Service interface provides a uniform way to manage the lifecycle of components that perform background tasks.

import com.google.common.util.concurrent.AbstractService;

public class MyService extends AbstractService {
    private final ExecutorService executor = Executors.newSingleThreadExecutor();

    @Override
    protected void doStart() {
        executor.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    performBackgroundTask();
                    notifyStarted();
                } catch (Throwable t) {
                    notifyFailed(t);
                }
            }
        });
    }

    @Override
    protected void doStop() {
        executor.shutdown();
        notifyStopped();
    }
}

Conclusion

Google Guava is a powerful, comprehensive library that provides a wide range of utilities for Java developers. Its features enhance the Java programming language, making code more readable, efficient, and less prone to errors. Although some of its functional programming features are now considered obsolete due to Java 8’s introduction of streams and lambda expressions, Guava’s other features, such as collections, caching, and concurrency utilities, continue to offer significant benefits to developers.

© Copyright 2024 by FriendlyUsers Tech Blog. Built with ♥ by FriendlyUser. Last updated on 2024-03-28.