Comprehensive Java library providing essential utilities, immutable collections, caching, and concurrency tools for modern Java development.
—
Additional utilities including event bus, escaping, networking, reflection, and primitive operations that provide specialized functionality for various programming needs.
Publish-subscribe event handling system that allows decoupled communication between components.
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import com.google.common.eventbus.AllowConcurrentEvents;
// Create event bus
EventBus eventBus = new EventBus("main-event-bus");
// Event classes
public class UserLoginEvent {
private final String username;
private final long timestamp;
public UserLoginEvent(String username) {
this.username = username;
this.timestamp = System.currentTimeMillis();
}
// Getters...
public String getUsername() { return username; }
public long getTimestamp() { return timestamp; }
}
public class OrderPlacedEvent {
private final String orderId;
private final String userId;
private final double amount;
// Constructor and getters...
}
// Event subscriber
public class UserActivityLogger {
@Subscribe
public void handleUserLogin(UserLoginEvent event) {
System.out.println("User logged in: " + event.getUsername() +
" at " + new Date(event.getTimestamp()));
// Log to database, send analytics, etc.
}
@Subscribe
@AllowConcurrentEvents // Indicates this method is thread-safe
public void handleOrderPlaced(OrderPlacedEvent event) {
System.out.println("Order placed: " + event.getOrderId() +
" by " + event.getUserId());
// Update user activity metrics
}
}
// Register subscribers and post events
UserActivityLogger logger = new UserActivityLogger();
eventBus.register(logger);
// Post events
eventBus.post(new UserLoginEvent("alice"));
eventBus.post(new OrderPlacedEvent("ORDER-123", "alice", 99.99));
// Unregister when no longer needed
eventBus.unregister(logger);Event bus that dispatches events asynchronously using a provided executor.
import com.google.common.eventbus.AsyncEventBus;
import java.util.concurrent.Executors;
// Create async event bus with custom executor
ExecutorService executor = Executors.newFixedThreadPool(4);
AsyncEventBus asyncEventBus = new AsyncEventBus("async-event-bus", executor);
// Subscriber methods run asynchronously
public class EmailNotificationService {
@Subscribe
public void sendWelcomeEmail(UserLoginEvent event) {
// This runs asynchronously
try {
Thread.sleep(2000); // Simulate email sending
System.out.println("Welcome email sent to " + event.getUsername());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
EmailNotificationService emailService = new EmailNotificationService();
asyncEventBus.register(emailService);
// This returns immediately, email is sent asynchronously
asyncEventBus.post(new UserLoginEvent("bob"));Handling events that have no subscribers and subscriber exceptions.
import com.google.common.eventbus.DeadEvent;
import com.google.common.eventbus.SubscriberExceptionHandler;
import com.google.common.eventbus.SubscriberExceptionContext;
// Handle events with no subscribers
public class DeadEventLogger {
@Subscribe
public void handleDeadEvent(DeadEvent deadEvent) {
Object event = deadEvent.getEvent();
EventBus source = deadEvent.getSource();
System.out.println("No subscribers for event: " + event.getClass().getSimpleName());
}
}
// Custom exception handler
SubscriberExceptionHandler exceptionHandler = new SubscriberExceptionHandler() {
@Override
public void handleException(Throwable exception, SubscriberExceptionContext context) {
System.err.println("Exception in subscriber: " + context.getSubscriberMethod());
System.err.println("Event: " + context.getEvent());
System.err.println("Subscriber: " + context.getSubscriber());
exception.printStackTrace();
// Could log to monitoring system, retry, etc.
}
};
// Create event bus with custom exception handler
EventBus eventBusWithErrorHandling = new EventBus(exceptionHandler);
// Register dead event handler
DeadEventLogger deadEventLogger = new DeadEventLogger();
eventBusWithErrorHandling.register(deadEventLogger);
// Post event with no subscribers - will be caught as DeadEvent
eventBusWithErrorHandling.post("This event has no subscriber");Immutable representation of network host and port combinations.
import com.google.common.net.HostAndPort;
// Parse host:port strings
HostAndPort hostPort1 = HostAndPort.fromString("example.com:8080");
HostAndPort hostPort2 = HostAndPort.fromString("192.168.1.1:80");
HostAndPort hostPort3 = HostAndPort.fromString("[::1]:8080"); // IPv6
// Create from components
HostAndPort hostPort4 = HostAndPort.fromParts("localhost", 3000);
HostAndPort hostOnly = HostAndPort.fromHost("example.com"); // No port
// Access components
String host = hostPort1.getHost(); // "example.com"
int port = hostPort1.getPort(); // 8080
boolean hasPort = hostOnly.hasPort(); // false
int portOrDefault = hostOnly.getPortOrDefault(80); // 80
// With default port
HostAndPort withDefault = hostOnly.withDefaultPort(8080);
// If hostOnly already has port, returns same instance; otherwise adds default
// String representation
String string = hostPort1.toString(); // "example.com:8080"
// Validation
try {
HostAndPort invalid = HostAndPort.fromString("invalid:port:format");
} catch (IllegalArgumentException e) {
// Handle malformed host:port string
}Working with domain names and public suffixes.
import com.google.common.net.InternetDomainName;
// Parse and validate domain names
InternetDomainName domain = InternetDomainName.from("mail.google.com");
// Validation
boolean isValid = InternetDomainName.isValid("example.com"); // true
boolean isValid2 = InternetDomainName.isValid("invalid..domain"); // false
// Domain hierarchy
List<String> parts = domain.parts(); // ["mail", "google", "com"]
InternetDomainName parent = domain.parent(); // "google.com"
InternetDomainName child = domain.child("inbox"); // "inbox.mail.google.com"
// Public suffix operations (requires public suffix list)
boolean isPublicSuffix = domain.isPublicSuffix(); // false
InternetDomainName publicSuffix = domain.publicSuffix(); // "com"
boolean isTopPrivateDomain = domain.isTopPrivateDomain(); // false ("google.com" would be true)
InternetDomainName topPrivate = domain.topPrivateDomain(); // "google.com"
// Domain relationships
InternetDomainName google = InternetDomainName.from("google.com");
InternetDomainName gmail = InternetDomainName.from("gmail.com");
boolean isUnder = domain.isUnder(google); // true (mail.google.com is under google.com)Working with IP addresses and network operations.
import com.google.common.net.InetAddresses;
import java.net.InetAddress;
// Parse IP address strings
InetAddress ipv4 = InetAddresses.forString("192.168.1.1");
InetAddress ipv6 = InetAddresses.forString("2001:db8::1");
// Validation
boolean isValid = InetAddresses.isInetAddress("192.168.1.1"); // true
boolean isValid2 = InetAddresses.isInetAddress("300.1.1.1"); // false
// Convert to string representation
String canonical = InetAddresses.toAddrString(ipv4); // "192.168.1.1"
String ipv6String = InetAddresses.toAddrString(ipv6); // "2001:db8::1"
// IP address manipulation
InetAddress incremented = InetAddresses.increment(ipv4); // 192.168.1.2
InetAddress decremented = InetAddresses.decrement(ipv4); // 192.168.1.0
// Check bounds
boolean isMax = InetAddresses.isMaximum(ipv4); // false
// IPv4/IPv6 conversions
InetAddress ipv4Addr = InetAddresses.forString("192.168.1.1");
InetAddress coerced = InetAddresses.getCoercedIPv4Address(ipv4Addr); // Same address
// Extract embedded IPv4 from IPv6 (for IPv4-mapped IPv6 addresses)
InetAddress embedded = InetAddresses.getEmbeddedIPv4ClientAddress(
InetAddresses.forString("::ffff:192.168.1.1")); // 192.168.1.1Working with MIME types and media type parsing.
import com.google.common.net.MediaType;
import java.nio.charset.StandardCharsets;
// Parse media types
MediaType json = MediaType.parse("application/json");
MediaType html = MediaType.parse("text/html; charset=utf-8");
MediaType pdf = MediaType.parse("application/pdf");
// Create media types
MediaType plainText = MediaType.create("text", "plain");
MediaType xmlUtf8 = MediaType.create("application", "xml")
.withCharset(StandardCharsets.UTF_8);
// Access components
String type = json.type(); // "application"
String subtype = json.subtype(); // "json"
String fullType = json.toString(); // "application/json"
// Parameters
Optional<Charset> charset = html.charset(); // Optional[UTF-8]
ImmutableListMultimap<String, String> parameters = html.parameters();
// Modify media types
MediaType withCharset = json.withCharset(StandardCharsets.UTF_8);
MediaType withParameter = json.withParameter("boundary", "----WebKitFormBoundary");
MediaType withoutParams = html.withoutParameters();
// Common media types (constants)
MediaType jpeg = MediaType.JPEG; // image/jpeg
MediaType css = MediaType.CSS; // text/css
MediaType javascript = MediaType.JAVASCRIPT_UTF_8; // application/javascript; charset=utf-8
// Type matching
boolean isJson = MediaType.JSON_UTF_8.is(MediaType.parse("application/json")); // true
boolean isText = MediaType.ANY_TEXT_TYPE.is(MediaType.PLAIN_TEXT_UTF_8); // trueSafe escaping for HTML and XML content.
import com.google.common.html.HtmlEscapers;
import com.google.common.xml.XmlEscapers;
import com.google.common.escape.Escaper;
// HTML escaping
Escaper htmlEscaper = HtmlEscapers.htmlEscaper();
String escaped = htmlEscaper.escape("<script>alert('XSS')</script>");
// Result: "<script>alert('XSS')</script>"
String userInput = "Tom & Jerry's \"Adventures\"";
String safeHtml = htmlEscaper.escape(userInput);
// Result: "Tom & Jerry's "Adventures""
// XML escaping
Escaper xmlContentEscaper = XmlEscapers.xmlContentEscaper();
Escaper xmlAttributeEscaper = XmlEscapers.xmlAttributeEscaper();
String xmlContent = xmlContentEscaper.escape("Data with <tags> & \"quotes\"");
// Result: "Data with <tags> & \"quotes\""
String xmlAttr = xmlAttributeEscaper.escape("Value with \"quotes\" & <brackets>");
// Result: "Value with "quotes" & <brackets>"
// Usage in templates
public String generateHtml(String title, String content) {
return "<html><head><title>" + htmlEscaper.escape(title) + "</title></head>" +
"<body>" + htmlEscaper.escape(content) + "</body></html>";
}Building custom escapers for specific needs.
import com.google.common.escape.Escapers;
import com.google.common.escape.CharEscaperBuilder;
// Build custom escaper
Escaper customEscaper = Escapers.builder()
.addEscape('\'', "\\'") // Escape single quotes
.addEscape('\"', "\\\"") // Escape double quotes
.addEscape('\\', "\\\\") // Escape backslashes
.addEscape('\n', "\\n") // Escape newlines
.addEscape('\t', "\\t") // Escape tabs
.toEscaper();
String input = "String with 'quotes' and \"escapes\"\nand newlines";
String escaped = customEscaper.escape(input);
// CSV escaper example
Escaper csvEscaper = Escapers.builder()
.addEscape('\"', "\"\"") // Double quote escaping for CSV
.toEscaper();
public String escapeCsvField(String field) {
if (field.contains("\"") || field.contains(",") || field.contains("\n")) {
return "\"" + csvEscaper.escape(field) + "\"";
}
return field;
}
// URL component escaper (for path segments, not full URLs)
Escaper urlEscaper = Escapers.builder()
.addEscape(' ', "%20")
.addEscape('!', "%21")
.addEscape('\"', "%22")
.addEscape('#', "%23")
// Add more as needed
.toEscaper();Utilities for working with primitive arrays and their wrapper types.
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import com.google.common.primitives.Doubles;
import com.google.common.primitives.Booleans;
// Array to List conversions
int[] intArray = {1, 2, 3, 4, 5};
List<Integer> intList = Ints.asList(intArray);
// List to array conversions
List<Integer> numbers = Arrays.asList(10, 20, 30);
int[] backToArray = Ints.toArray(numbers);
// Array operations
boolean contains = Ints.contains(intArray, 3); // true
int index = Ints.indexOf(intArray, 4); // 3
int lastIndex = Ints.lastIndexOf(intArray, 2); // 1
// Min/Max operations
int min = Ints.min(intArray); // 1
int max = Ints.max(intArray); // 5
// Joining arrays as strings
String joined = Ints.join(", ", intArray); // "1, 2, 3, 4, 5"
// Lexicographical comparison
Comparator<int[]> comparator = Ints.lexicographicalComparator();
int comparison = comparator.compare(new int[]{1, 2}, new int[]{1, 3}); // -1
// Similar operations for other primitive types
long[] longArray = {1L, 2L, 3L};
List<Long> longList = Longs.asList(longArray);
long maxLong = Longs.max(longArray);
double[] doubleArray = {1.1, 2.2, 3.3};
boolean isFinite = Doubles.isFinite(2.2); // true (not NaN or infinity)
boolean[] boolArray = {true, false, true, true};
int trueCount = Booleans.countTrue(boolArray); // 3Safe parsing of strings to primitive types.
// Safe parsing (returns null for invalid input)
Integer parsed = Ints.tryParse("123"); // 123
Integer invalid = Ints.tryParse("abc"); // null
Integer overflow = Ints.tryParse("999999999999999999"); // null (overflow)
Long longParsed = Longs.tryParse("123456789");
Double doubleParsed = Doubles.tryParse("3.14159");
// String converters (for use with Functions)
Function<String, Integer> intConverter = Ints.stringConverter();
Function<Integer, String> intToString = intConverter.reverse();
// Usage with collections
List<String> stringNumbers = Arrays.asList("1", "2", "3", "invalid", "5");
List<Integer> validNumbers = stringNumbers.stream()
.map(Ints::tryParse)
.filter(Objects::nonNull)
.collect(Collectors.toList()); // [1, 2, 3, 5]Working with unsigned integer values.
import com.google.common.primitives.UnsignedInteger;
import com.google.common.primitives.UnsignedLong;
import com.google.common.primitives.UnsignedInts;
import com.google.common.primitives.UnsignedLongs;
// Unsigned integers
UnsignedInteger uint1 = UnsignedInteger.valueOf(0x80000000L); // Large positive value
UnsignedInteger uint2 = UnsignedInteger.valueOf("4294967295"); // Max unsigned 32-bit
// Arithmetic operations
UnsignedInteger sum = uint1.plus(uint2);
UnsignedInteger difference = uint1.minus(uint2);
UnsignedInteger product = uint1.times(UnsignedInteger.valueOf(2));
UnsignedInteger quotient = uint1.dividedBy(UnsignedInteger.valueOf(2));
// Comparison
int comparison = uint1.compareTo(uint2);
// Conversion
long asLong = uint1.longValue(); // As signed long
String asString = uint1.toString();
// Unsigned longs (for values larger than signed long max)
UnsignedLong ulong1 = UnsignedLong.valueOf(new BigInteger("18446744073709551615")); // Max unsigned 64-bit
UnsignedLong ulong2 = UnsignedLong.valueOf("9223372036854775808"); // Just over signed long max
// Static utility methods for unsigned operations
int unsignedComparison = UnsignedInts.compare(0x80000000, 0x7FFFFFFF); // 1 (first is larger unsigned)
int signedComparison = Integer.compare(0x80000000, 0x7FFFFFFF); // -1 (first is negative signed)
long unsignedDivision = UnsignedInts.divide(0x80000000, 2); // Correct unsigned division
String unsignedString = UnsignedInts.toString(0x80000000); // "2147483648"
// Parsing unsigned values
int parsedUnsigned = UnsignedInts.parseUnsignedInt("4294967295"); // Max unsigned 32-bit
long parsedUnsignedLong = UnsignedLongs.parseUnsignedLong("18446744073709551615");Type-safe reflection for generic types.
import com.google.common.reflect.TypeToken;
import java.lang.reflect.Type;
// Capture generic types at runtime
TypeToken<List<String>> stringListToken = new TypeToken<List<String>>() {};
TypeToken<Map<String, Integer>> mapToken = new TypeToken<Map<String, Integer>>() {};
// Get type information
Type listType = stringListToken.getType(); // java.util.List<java.lang.String>
Class<? super List<String>> rawType = stringListToken.getRawType(); // class java.util.List
// Type relationships
TypeToken<ArrayList<String>> arrayListToken = new TypeToken<ArrayList<String>>() {};
boolean isSubtype = arrayListToken.isSubtypeOf(stringListToken); // true
TypeToken<List<Object>> objectListToken = new TypeToken<List<Object>>() {};
boolean isSuper = objectListToken.isSupertypeOf(stringListToken); // true
// Resolve generic types in inheritance hierarchy
class StringList extends ArrayList<String> {}
TypeToken<StringList> stringListSubclass = TypeToken.of(StringList.class);
TypeToken<?> resolvedSupertype = stringListSubclass.getSupertype(List.class);
// Resolves to List<String>
// Working with method return types and parameters
public class GenericService<T> {
public List<T> getItems() { return null; }
public void setItems(List<T> items) {}
}
TypeToken<GenericService<String>> serviceToken = new TypeToken<GenericService<String>>() {};
Method getItemsMethod = GenericService.class.getMethod("getItems");
TypeToken<?> returnType = serviceToken.resolveType(getItemsMethod.getGenericReturnType());
// Resolves to List<String>Scanning the classpath to find classes and resources.
import com.google.common.reflect.ClassPath;
import java.util.Set;
// Scan classpath
ClassPath classPath = ClassPath.from(Thread.currentThread().getContextClassLoader());
// Find all classes
Set<ClassPath.ClassInfo> allClasses = classPath.getAllClasses();
// Find classes in specific package
String packageName = "com.example.services";
Set<ClassPath.ClassInfo> packageClasses = classPath.getTopLevelClasses(packageName);
// Find classes recursively in package hierarchy
Set<ClassPath.ClassInfo> recursiveClasses = classPath.getTopLevelClassesRecursive(packageName);
// Load and filter classes
List<Class<?>> serviceClasses = packageClasses.stream()
.map(ClassPath.ClassInfo::load)
.filter(clazz -> clazz.getSimpleName().endsWith("Service"))
.collect(Collectors.toList());
// Find classes by annotation
List<Class<?>> annotatedClasses = allClasses.stream()
.map(ClassPath.ClassInfo::load)
.filter(clazz -> clazz.isAnnotationPresent(Component.class))
.collect(Collectors.toList());
// Resource scanning
Set<ClassPath.ResourceInfo> resources = classPath.getResources();
Optional<ClassPath.ResourceInfo> configResource = resources.stream()
.filter(resource -> resource.getResourceName().endsWith("application.properties"))
.findFirst();Type-safe wrapper for Method and Constructor with better generic support.
import com.google.common.reflect.Invokable;
import com.google.common.reflect.Parameter;
import java.lang.reflect.Method;
// Wrap methods
Method method = String.class.getMethod("substring", int.class, int.class);
Invokable<String, String> substringInvokable = Invokable.from(method);
// Type-safe invocation
String result = substringInvokable.invoke("Hello World", 0, 5); // "Hello"
// Generic type information
TypeToken<String> returnType = substringInvokable.getReturnType();
List<Parameter> parameters = substringInvokable.getParameters();
// Parameter information
Parameter firstParam = parameters.get(0);
TypeToken<?> paramType = firstParam.getType(); // TypeToken for int
boolean isAnnotated = firstParam.isAnnotationPresent(SomeAnnotation.class);
// Constructor wrapping
Constructor<ArrayList> constructor = ArrayList.class.getConstructor(int.class);
Invokable<Void, ArrayList> constructorInvokable = Invokable.from(constructor);
ArrayList<String> list = constructorInvokable.invoke(null, 10); // Initial capacity 10
// Exception types
ImmutableList<TypeToken<? extends Throwable>> exceptionTypes =
substringInvokable.getExceptionTypes();Real-world examples combining various utilities.
// Event-driven application architecture
public class OrderProcessingSystem {
private final EventBus eventBus;
private final PaymentService paymentService;
private final InventoryService inventoryService;
private final NotificationService notificationService;
public OrderProcessingSystem() {
this.eventBus = new EventBus("order-processing");
this.paymentService = new PaymentService();
this.inventoryService = new InventoryService();
this.notificationService = new NotificationService();
// Register all services as event subscribers
eventBus.register(paymentService);
eventBus.register(inventoryService);
eventBus.register(notificationService);
}
public void processOrder(Order order) {
// Validate order
if (order.getAmount() <= 0) {
eventBus.post(new OrderRejectedEvent(order, "Invalid amount"));
return;
}
// Post order received event
eventBus.post(new OrderReceivedEvent(order));
}
public static class OrderReceivedEvent {
private final Order order;
public OrderReceivedEvent(Order order) { this.order = order; }
public Order getOrder() { return order; }
}
public static class OrderRejectedEvent {
private final Order order;
private final String reason;
public OrderRejectedEvent(Order order, String reason) {
this.order = order;
this.reason = reason;
}
// Getters...
}
}
// Web API parameter parsing
public class ApiParameterParser {
public static Optional<Integer> parseIntParameter(String value) {
return Optional.fromNullable(Ints.tryParse(value));
}
public static List<Integer> parseIntList(String value) {
if (Strings.isNullOrEmpty(value)) {
return Collections.emptyList();
}
return Splitter.on(',')
.trimResults()
.omitEmptyStrings()
.splitToList(value)
.stream()
.map(Ints::tryParse)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
public static String sanitizeUserInput(String input) {
if (input == null) return "";
// Escape HTML to prevent XSS
return HtmlEscapers.htmlEscaper().escape(input.trim());
}
}
// Configuration management with type safety
public class ConfigurationManager {
private final Map<String, String> properties;
private final Escaper propertyEscaper;
public ConfigurationManager(Properties props) {
this.properties = Maps.fromProperties(props);
this.propertyEscaper = Escapers.builder()
.addEscape('\\', "\\\\")
.addEscape('=', "\\=")
.addEscape(':', "\\:")
.toEscaper();
}
public Optional<String> getString(String key) {
return Optional.fromNullable(properties.get(key));
}
public Optional<Integer> getInt(String key) {
return getString(key).transform(Ints::tryParse);
}
public Optional<Boolean> getBoolean(String key) {
return getString(key).transform(Boolean::parseBoolean);
}
public List<String> getStringList(String key) {
return getString(key)
.transform(value -> Splitter.on(',').trimResults().splitToList(value))
.or(Collections.emptyList());
}
public HostAndPort getHostAndPort(String key) {
return getString(key)
.transform(HostAndPort::fromString)
.orNull();
}
}
// Service discovery with networking utilities
public class ServiceRegistry {
private final Map<String, Set<HostAndPort>> services = new ConcurrentHashMap<>();
public void registerService(String serviceName, String hostPort) {
try {
HostAndPort parsed = HostAndPort.fromString(hostPort);
services.computeIfAbsent(serviceName, k -> ConcurrentHashMap.newKeySet())
.add(parsed);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Invalid host:port format: " + hostPort, e);
}
}
public Optional<HostAndPort> getServiceEndpoint(String serviceName) {
Set<HostAndPort> endpoints = services.get(serviceName);
if (endpoints == null || endpoints.isEmpty()) {
return Optional.absent();
}
// Simple round-robin selection
return Optional.of(endpoints.iterator().next());
}
public boolean isValidServiceEndpoint(String hostPort) {
try {
HostAndPort.fromString(hostPort);
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
}These utilities provide essential functionality for building robust applications with proper input validation, event-driven architectures, network communication, and type-safe operations while maintaining clean, readable code.
Install with Tessl CLI
npx tessl i tessl/maven-com-google-guava--guava