December 30, 2013

In this post, I will go through a quick overiew of a few uses of Google’s Guava library. When I entered the professional world, I used Guava pretty heavily and the following blog post includes some of the notes I took when learning about Guava’s many useful tools.

What is Guava?

Guava is a open-source library for the Java language that provides several utilities that makes a programmer’s job easier. According to Jared Levy (one of the creators of Java), “The library’s functionality simplifies your code so it’s easier to write, read, and maintain”. This wiki page is designed to introduce some useful aspects of Guava and expose some gotchas that you might come across. It includes utilities for Collections, Concurrency, Primitives, Reflection, Comparison, I/O, Hashing, Networking, Strings, Math, In-memory caching, and various basic data types.

Useful utility classes

Preconditions: Used to validate assumptions at the start of methods or constructors (and fail-fast if they aren’t valid)

public Person(Name name) {
  this.name = Preconditions.checkNotNull(name); // throws NullPointerException
}
 
public void eat(Food food) {
  Preconditions.checkArgument(food.isPoisonous(), "Food must not be poisonous"); // throws IllegalArgumentException
  Preconditions.checkState(person.isHungry(), "Person must be running"); // throws IllegalStateException
  ...
}

Objects: simplify writing equals(), toString(), hashCode() for a class

// Objects.equal provides null-sensitive comparison 
Objects.equal("a", "a"); // returns true
Objects.equal(null, "a"); // returns false
Objects.equal("a", null); // returns false
Objects.equal(null, null); // returns true
 
// Objects.hashCode provides a order-sensitive hashCode method for a variable number of args. Uses Arrays.hashCode
Objects.hashCode(person.getName(), person.getAge());
 
// Objects.toStringHelper provides a easy, clean way to implement a class' toString method, overloaded add() methods for each primitive data type
Objects.toStringHelper("Person") // returns Person{age=43}
       .add("age", 43)
       .add("hungry", null)
       .omitNullValues()
       .toString();

NOTE: Java 7 provides a new Objects class that provides similar functionality.

Strings: simplify String joining, splitting, matching

// Joiner provides utility methods to join pieces of text into a String
static final Joiner JOINER = Joiner.on("-").skipNulls();
return JOINER.join("Me", null, "Myself", "I"); // returns "Me-Myself-I"
 
// Splitter provides utility methods to split a given String into pieces of text split by a given separator
static final Splitter SPLITTER = Splitter.on(',').trimResults().omitEmptyStrings();
return SPLITTER.split("me,myself,,    I"); // returns an Iterable of ["me", "myself", "I"]
 
// CharMatcher has several common matchers and methods to [trim|replace|remove|return|collapsing] occurrences of a match in a String
String onlyDigits = CharMatcher.DIGIT.retainFrom(string); // keep only the digits
String noDigits = CharMatcher.JAVA_DIGIT.replaceFrom(string, "*"); // replace all digits with stars

Functional Programming: Functions and Predicates that can be used to simulate first-class functions in Java

// Function<F, T>: Override equals method to provide a one-way transformation of F to T
static final Function<String, Integer> LENGTH = new Function<String, Integer>() {
  public Integer apply(String string) {
    return string.length();
  }
};
 
// Predicate<F>: Override apply method to determine if F is true or false
static final Predicate<String> ALL_CAPS = new Predicate<String>() {
  public boolean apply(String string) {
    return CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string);
  }
};

IntMath/LongMath

Guava provides utility methods for performing int, long, BigInteger operations in conveniently named IntMath, LongMath, and BigIntegerMath classes. IntMath and LongMath provide overflow-checked add, subtract, multiply and divide methods. These methods fail-fast on overflow. Here are some examples of using the utility methods:

int x = 3;
int y = 45;
long l = 21520;
 
MathPreconditions.checkPositive(x); // returns 3
  
IntMath.factorial(x); // returns 6
IntMath.gcd(x, y) // returns 3
IntMath.isPowerOfTwo(x) // returns false
LongMath.mod(l, 10); //returns 0

Guava Pitfalls/Gotchas

  • Joiner/Splitter instances are always immutable:
// This has no effect:
Joiner joiner = Joiner.on(',');
joiner.skipNulls(); // does nothing!
return joiner.join("bad", null, "wrong");
 
 // Do this instead:
 Joiner joiner = Joiner.on(',').skipNulls();
 Guava has several methods that returns views. Views modify underlying collection:

Scala: The Good Parts

Quick overview of some features of the Scala Programming Language Continue reading

Design Patterns in Real Life

Published on December 05, 2014

Introduction to ZooKeeper

Published on August 16, 2014