Guide to Google Guava Library in Java

Introduction

Google Guava is an open-source Java-based library developed by Google that provides essential utilities for Java projects. It includes features for collections, caching, primitives support, concurrency, common annotations, string processing, I/O, and more. By leveraging Guava, developers can write cleaner, more efficient, and less error-prone code.

Installation

To use Google Guava, add the following dependency to your pom.xml if you're using Maven:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.0.1-jre</version> <!-- or the latest version -->
</dependency>

For Gradle:

implementation 'com.google.guava:guava:31.0.1-jre' // or the latest version

Collections

Immutable Collections

Immutable collections cannot be modified after they are created. This is useful for thread safety and ensuring that collections remain constant throughout their lifecycle.

Example

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

public class ImmutableCollectionsExample {
    public static void main(String[] args) {
        ImmutableList<String> list = ImmutableList.of("a", "b", "c");
        ImmutableSet<String> set = ImmutableSet.of("a", "b", "c");
        ImmutableMap<String, Integer> map = ImmutableMap.of("a", 1, "b", 2, "c", 3);

        System.out.println("Immutable List: " + list);
        System.out.println("Immutable Set: " + set);
        System.out.println("Immutable Map: " + map);
    }
}

Multimap

A Multimap is a collection that maps keys to values, where each key may be associated with multiple values.

Example

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

public class MultimapExample {
    public static void main(String[] args) {
        Multimap<String, String> multimap = ArrayListMultimap.create();
        multimap.put("fruit", "apple");
        multimap.put("fruit", "banana");
        multimap.put("vegetable", "carrot");

        System.out.println("Multimap: " + multimap);
    }
}

BiMap

A BiMap is a map that guarantees the uniqueness of its values and its keys, allowing for value-to-key lookups.

Example

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

public class BiMapExample {
    public static void main(String[] args) {
        BiMap<String, Integer> biMap = HashBiMap.create();
        biMap.put("one", 1);
        biMap.put("two", 2);

        System.out.println("BiMap: " + biMap);
        System.out.println("Inverse BiMap: " + biMap.inverse());
    }
}

Table

A Table is a collection that represents a mapping between two keys to a single value, similar to a two-dimensional map.

Example

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

public class TableExample {
    public static void main(String[] args) {
        Table<String, String, Integer> table = HashBasedTable.create();
        table.put("row1", "column1", 1);
        table.put("row1", "column2", 2);
        table.put("row2", "column1", 3);

        System.out.println("Table: " + table);
    }
}

Caching

Guava provides a powerful and flexible caching API that can be used to create and manage caches.

Example

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

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class CacheExample {
    public static void main(String[] args) throws ExecutionException {
        LoadingCache<String, String> cache = CacheBuilder.newBuilder()
                .maximumSize(100)
                .expireAfterWrite(10, TimeUnit.MINUTES)
                .build(new CacheLoader<>() {
                    public String load(String key) {
                        return getDataFromDatabase(key);
                    }
                });

        System.out.println("Cache Value: " + cache.get("key"));
    }

    private static String getDataFromDatabase(String key) {
        return "value"; // Simulated database call
    }
}

Strings

Guava offers various utilities for working with strings, such as joining, splitting, and manipulation.

Example: Joiner

import com.google.common.base.Joiner;

public class JoinerExample {
    public static void main(String[] args) {
        Joiner joiner = Joiner.on(", ").skipNulls();
        String result = joiner.join("Harry", null, "Ron", "Hermione");
        System.out.println("Joined String: " + result);
    }
}

Example: Splitter

import com.google.common.base.Splitter;

public class SplitterExample {
    public static void main(String[] args) {
        Iterable<String> result = Splitter.on(',').trimResults().omitEmptyStrings().split("foo,bar,,   qux");
        result.forEach(System.out::println);
    }
}

Primitives

Guava provides utilities for working with primitive types, such as Ints, Longs, and Doubles.

Example

import com.google.common.primitives.Ints;

public class PrimitivesExample {
    public static void main(String[] args) {
        int[] array = {1, 2, 3, 4, 5};
        System.out.println("Contains 3: " + Ints.contains(array, 3));
        System.out.println("Max: " + Ints.max(array));
        System.out.println("Min: " + Ints.min(array));
    }
}

Concurrency

Guava provides utilities to simplify concurrency tasks, such as ListeningExecutorService, which extends ExecutorService to support ListenableFuture.

Example

import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;

import java.util.concurrent.Callable;
import java.util.concurrent.Executors;

public class ConcurrencyExample {
    public static void main(String[] args) throws Exception {
        ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
        ListenableFuture<String> future = service.submit(new Callable<>() {
            public String call() {
                return "Task Result";
            }
        });

        future.addListener(() -> System.out.println("Task completed!"), MoreExecutors.directExecutor());
        System.out.println("Result: " + future.get());
    }
}

I/O

Guava simplifies common I/O tasks, such as reading and writing files, with the Files class.

Example

import com.google.common.io.Files;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class IOExample {
    public static void main(String[] args) throws IOException {
        File file = new File("example.txt");
        String content = "Hello, Guava!";
        Files.asCharSink(file, StandardCharsets.UTF_8).write(content);

        String readContent = Files.asCharSource(file, StandardCharsets.UTF_8).read();
        System.out.println("File Content: " + readContent);
    }
}

More Examples and Use Cases

Preconditions

Guava provides a Preconditions class that simplifies checking conditions in your code. This is particularly useful for validating method arguments.

Example

import com.google.common.base.Preconditions;

public class PreconditionsExample {
    public static void main(String[] args) {
        int age = -5;
        Preconditions.checkArgument(age > 0, "Age must be positive");
    }
}

Optional

Guava's Optional class is used to represent optional (nullable) values without using null references.

Example

import com.google.common.base.Optional;

public class OptionalExample {
    public static void main(String[] args) {
        Optional<Integer> possible = Optional.of(5);
        System.out.println("Is present: " + possible.isPresent());
        System.out.println("Value: " + possible.get());

        Optional<Integer> absent = Optional.absent();
        System.out.println("Is present: " + absent.isPresent());
    }
}

Ordering

The Ordering class is a rich utility for creating and working with comparators.

Example

import com.google.common.collect.Ordering;

import java.util.Arrays;
import java.util.List;

public class OrderingExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Dave");
        Ordering<String> byLength = Ordering.natural().onResultOf(String::length);
        List<String> sortedNames = byLength.sortedCopy(names);
        System.out.println("Sorted by length: " + sortedNames);
    }
}

Range

The Range class is used to represent a contiguous range of values.

Example

import com.google.common.collect.Range;

public class RangeExample {
    public static void main(String[] args) {
        Range<Integer> range = Range.closed(1, 10);
        System.out.println("Range: " + range);
        System.out.println("Contains 5: " + range.contains(5));
        System.out.println("Contains 15: " + range.contains(15));
    }
}

EventBus

The EventBus is a publish/subscribe event system that simplifies communication between components.

Example

import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;

public class EventBusExample {
    public static void main(String[] args) {
        EventBus eventBus = new EventBus();
        eventBus.register(new EventListener());

        eventBus.post(new EventMessage("Hello EventBus!"));
    }

    static class EventMessage {
        private final String message;

        public EventMessage(String message) {
            this.message = message;
        }

        public String getMessage() {
            return message;
        }
    }

    static class EventListener {
        @Subscribe
        public void listen(EventMessage eventMessage) {
            System.out.println("Received message: " + eventMessage.getMessage());
        }
    }
}

Stopwatch

The Stopwatch class provides a simple API for timing operations.

Example

import com.google.common.base.Stopwatch;

import java.util.concurrent.TimeUnit;

public class StopwatchExample {
    public static void main(String[] args) throws InterruptedException {
        Stopwatch stopwatch = Stopwatch.createStarted();
        TimeUnit.SECONDS.sleep(2);
        stopwatch.stop();

        System.out.println("Elapsed time: " + stopwatch.elapsed(TimeUnit.SECONDS) + " seconds");
    }
}

More Objects

Guava provides the MoreObjects class, which offers utility methods for working with objects, such as toStringHelper for generating toString methods.

Example

import com.google.common.base.MoreObjects;

public class MoreObjectsExample {
    private final String name;
    private final int age;

    public MoreObjectsExample(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("name", name)
                .add("age", age)
                .toString();
    }

    public static void main(String[] args) {
        MoreObjectsExample example = new MoreObjectsExample("John", 25);
        System.out.println(example);
    }
}

Hashing

Guava provides a powerful hashing library that includes various hashing algorithms.

Example

import com.google.common.hash.Hashing;
import com.google.common.hash.HashFunction;
import com.google.common.hash.HashCode;

import java.nio.charset.StandardCharsets;

public class HashingExample {
    public static void main(String[] args) {
        HashFunction hashFunction = Hashing.sha256();
        HashCode hashCode = hashFunction.hashString("hello world", StandardCharsets.UTF_8);
        System.out.println("Hash code: " + hashCode);
    }
}

CharMatcher

The CharMatcher class provides utilities for working with characters and strings.

Example

import com.google.common.base.CharMatcher;

public class CharMatcherExample {
    public static void main(String[] args) {
        String input = "123abcXYZ";
        String digits = CharMatcher.digit().retainFrom(input);
        String letters = CharMatcher.javaLetter().retainFrom(input);

        System.out.println("Digits: " + digits);
        System.out.println("Letters: " + letters);
    }
}

Files

Guava's Files class provides utilities for working with files, such as creating temporary directories and simplifying file operations.

Example: Create Temporary Directory

import com.google.common.io.Files;

import java.io.File;
import java.io.IOException;

public class CreateTempDirExample {
    public static void main(String[] args) throws IOException {
        File tempDir = Files.createTempDir();
        System.out.println("Temporary Directory: " + tempDir.getAbsolutePath());
    }
}

Example: Simplified File Operations

import com.google.common.io.Files;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class SimplifiedFileOperationsExample {
    public static void main(String[] args) throws IOException {
        File file = new File("example.txt");
        String content = "Hello, Guava!";
        Files.asCharSink(file, StandardCharsets.UTF_8).write(content);

        String readContent = Files.asCharSource(file, StandardCharsets.UTF_8).read();
        System.out.println("File Content: " + readContent);
    }
}

Throwables

Guava provides the Throwables class to simplify working with exceptions.

Example

import com.google.common.base.Throwables;

public class ThrowablesExample {
    public static void main(String[] args) {
        try {
            throw new RuntimeException("Example exception");
        } catch (RuntimeException e) {
            System.out.println("Stack trace: " + Throwables.getStackTraceAsString(e));
        }
    }
}

ComparisonChain

The ComparisonChain class simplifies implementing compareTo methods.

Example

import com.google.common.collect.ComparisonChain;

public class ComparisonChainExample implements Comparable<ComparisonChainExample> {
    private final String name;
    private final int age;

    public ComparisonChainExample(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public int compareTo(ComparisonChainExample other) {
        return ComparisonChain.start()
                .compare(this.name, other.name)
                .compare(this.age, other.age)
                .result();
    }

    public static void main(String[] args) {
        ComparisonChainExample a = new ComparisonChainExample("John", 25);
        ComparisonChainExample b = new ComparisonChainExample("John", 30);

        System.out.println("Comparison result: " + a.compareTo(b));
    }
}

Conclusion

Google Guava is a powerful library that enhances Java development by providing utilities for collections, caching, concurrency, I/O, and more. This tutorial covered essential use cases and examples to get you started with Guava. For more advanced features and detailed documentation, visit the official Guava documentation.

With Guava, you can write more efficient, readable, and maintainable Java code by taking advantage of its rich set of tools.

Comments