An Overview of Guava:
Google Core Libraries
for Java
Kevin Bourrillion
Java Core Libraries Team
Google, Inc.
Presented at QCon November 8, 2012
Google Confidential and Proprietary
What's Guava?
Free open-source library for Java, GWT, Android.
14 packages chock full of utility classes and methods:
annotations
base
cache
collect
collect.testing
eventbus
hash
io
math
net
primitives
reflect
testing
util.concurrent
(These packages live under com.google.common.)
Google Confidential and Proprietary
Where does it come from?
We are the Java Core Libraries Team at Google.
What do we do?
Why do we release Guava?
It's a junk drawer then?
Why are you here talking about it?
Google Confidential and Proprietary
Actual User Quotes
On any new Java project, the first thing I do is add a
dependency to Guava; I just know Im going to need it.
Writing Java without Guava was like coding with one hand
tied behind my back.
Guava makes Java bearable again.
(We happen to think Java is more than bearable anyway,
but still: Guava makes writing Java programs easier.)
*paraphrased. But I swear people really said these things. Honest.
Google Confidential and Proprietary
About this presentation
Google Confidential and Proprietary
com.google.common.base
Google Confidential and Proprietary
String joining
Who here has ever written this utility?
public class StringUtil {
public static String join(
String separator, Iterable<String> pieces) {
// any of ~5 common implementations goes here
}
}
Google Confidential and Proprietary
String joining 2
But what about all the variations?
What to do with nulls?
skip over them? skip but leave separator? substitute
"null" or some other string? Just die?
Joining an Iterable, Iterator, varargs/array?
Return a String, or append to an Appendable?
We could be looking at 18 to 48 different methods here.
To cover all these bases we made Joiner:
return Joiner.on(", ")
.skipNulls()
.join("one", null, "two", "three");
Google Confidential and Proprietary
Joiner: what's going on here?
To get a Joiner:
static Joiner on(String)
static Joiner on(char)
To get an altered Joiner from that:
Joiner skipNulls()
Joiner useForNull(String)
To actually join stuff:
String join(Itera___)
String join(Object...)
Appendable appendTo(Appendable, Itera___)
Appendable appendTo(Object...)
Google Confidential and Proprietary
Splitter
Similar! But in the other direction.
return Splitter.on("|")
.omitEmptyStrings()
.split("|Harry||Ron|||Hermione
// returns "Harry", "Ron", "Hermione
||");
";
These classes use what we (tentatively) call the "Utility
Object pattern."
Google Confidential and Proprietary
CharMatcher (motivation)
Once upon a time we had a StringUtil class. Soon it was
overflowing with static methods:
allAscii, collapse, collapseControlChars,
collapseWhitespace, indexOfChars, lastIndexNotOf,
numSharedChars, removeChars, removeCrLf, replaceChars,
retainAllChars, strip, stripAndCollapse,
stripNonDigits...
Each dealt with two orthogonal concerns:
(a) what does it consider a matching character?
(b) what do we do with these matching characters?
One static method per combination would not scale.
Google Confidential and Proprietary
CharMatcher
Once again we use the Utility Object pattern.
A CharMatcher instance represents the set of "matching"
characters (part "a"). Methods on that instance provide the
operations (part "b").
// "_34-425==" becomes "34425"
String sanitized =
CharMatcher.anyOf("-=_")
.removeFrom(input);
Separates "configuration" from "processing".
Google Confidential and Proprietary
Getting a CharMatcher
Use a predefined constant (examples)
CharMatcher.WHITESPACE (Unicode)
CharMatcher.ASCII
CharMatcher.ANY
Use a factory method (examples)
CharMatcher.is('x')
CharMatcher.isNot('_')
CharMatcher.oneOf("aeiou")
CharMatcher.inRange('a', 'z')
.or(inRange('A', 'Z')).negate()
Or subclass CharMatcher, implement matches(char).
Google Confidential and Proprietary
Using your new CharMatcher
boolean matchesAllOf(CharSequence)
boolean matchesAnyOf(CharSequence)
boolean matchesNoneOf(CharSequence)
int indexIn(CharSequence, int)
int lastIndexIn(CharSequence, int)
int countIn(CharSequence)
String
String
String
String
String
String
String
String
removeFrom(CharSequence)
retainFrom(CharSequence)
trimFrom(CharSequence)
trimLeadingFrom(CharSequence)
trimTrailingFrom(CharSequence)
collapseFrom(CharSequence, char)
trimAndCollapseFrom(CharSequence, char)
replaceFrom(CharSequence, char)
Google Confidential and Proprietary
CharMatcher (last)
Putting it back together... to scrub an id number, you might
use
String seriesId =
CharMatcher.DIGIT.or(CharMatcher.is('-'))
.retainFrom(input);
In a loop? Move the definition above or to a constant.
static final CharMatcher ID_CHARS =
CharMatcher.DIGIT.or(CharMatcher.is('-'));
...
String id = SERIES_ID_CHARS.retainFrom(input);
Google Confidential and Proprietary
One problem with null
Consider looking up a phone number.
PhoneNumber phone = phoneBook.lookUp("Barack");
if (phone == null) {
// what does this mean?
}
No entry? Or entry exists but the phone number is unlisted?
Or consider a nickname field. null means no nickname, or
we just don't know?
Google Confidential and Proprietary
Optional<T>
Guava's Optional class lets you have a "second kind of
not-there" -- a "positive negative."
// Yes, has a nickname
Optional<String> nickname = Optional.of("Barry");
// Yes, we have no nickname
Optional<String> nickname = Optional.absent();
// Information missing/unknown
Optional<String> nickname = null;
// wat? Throws an exception.
Optional<String> nickname = Optional.of(null);
Google Confidential and Proprietary
Optional<T> basic usage
Optional<String> nickname = person.nickname();
if (nickname == null) return;
if (nickname.isPresent()) {
say("I hear people call you " + nickname.get());
} else {
// calling get() would throw an exception!
say("Your friends are not creative.");
}
Google Confidential and Proprietary
Optional<T> cooler usages
for (String actualNick : nickname.asSet()) {
doSomething(actualNick);
}
or
String firstName = person.firstName();
say("Hello, " + nickname.or(firstName));
Google Confidential and Proprietary
For null-unfriendly
collections
Many collections, including the JDK's Queue and
ConcurrentMap implementations, don't allow null elements.
Queue<Optional<Foo>> is a simple and natural solution!
Google Confidential and Proprietary
Optional<T>: the anti-null?
Some users use Optional even when they have only one
"kind of not-there". They use it as a null replacement.
Before:
Foo foo = someMethodThatMightReturnNull();
foo.whoops(); // I just forgot to check!
After:
Optional<Foo> foo = someMethod();
foo.get().whoops(); // same mistake!
Same mistake possible, but less likely to some degree.
Especially appropriate for public method return types.
Google Confidential and Proprietary
Stopwatch
For measuring elapsed time. Don't use System.
currentTimeMillis()!
Stopwatch watch = new Stopwatch().start();
doSomeOperation();
long micros = watch.elapsedTime(MICROSECONDS);
Stopwatch uses nanoTime() but exposes only relative
timings, a meaningless absolute value
an alternate time source can be substituted using
Ticker
has the same functions as a physical stopwatch
toString() gives human readable format
Google Confidential and Proprietary
Other things in base
... that we're not really going into ...
Preconditions
Objects.toStringHelper()
Objects.firstNonNull(T, T)
Throwables.propagate(Throwable)
CaseFormat
Strings.repeat(String, int)
Equivalence<T>
Function, Predicate, Supplier
Google Confidential and Proprietary
com.google.common.collect
Google Confidential and Proprietary
Collection Types (review)
Set:
doesn't guarantee order, has "unordered equality"
collapses duplicates
List:
guarantees order, has "ordered equality"
allows duplicates (multiple "occurrences")
Aren't these two orthogonal concerns?
Google Confidential and Proprietary
Basic Collection Types
Ordered?
Y
N
+------------+----------+
Y |
List
|
?
|
Dups?
+------------+----------+
N |
?
|
Set
|
+------------+----------+
Google Confidential and Proprietary
Basic Collection Types
Ordered?
Y
N
+------------+----------+
Y |
List
| Multiset |
Dups?
+------------+----------+
N |(UniqueList)|
Set
|
+------------+----------+
Google Confidential and Proprietary
Multiset<E>
Implements Collection<E>.
List:
[a, c, b, b, c, a, a, b]
Set:
[a, c, b]
Multiset: [a, a, a, c, c, b, b, b]
So a Multiset implementation only needs to store one
occurrence of each element, plus a count!
[a x 3, c x 2, b x 3]
Google Confidential and Proprietary
Counting without Multiset
Map<String, Integer> tags = new HashMap<>();
for (BlogPost post : getAllBlogPosts()) {
for (String tag : post.getTags()) {
int value = tags.containsKey(tag) ? tags.get(tag) : 0;
tags.put(tag, value + 1);
}
}
distinct tags: tags.keySet()
count for "java" tag:
tags.containsKey("java") ? tags.get("java") : 0;
total count: // uh oh...
Google Confidential and Proprietary
Counting with Multiset
Multiset<String> tags = HashMultiset.create();
for (BlogPost post : getAllBlogPosts()) {
tags.addAll(post.getTags());
}
distinct tags: tags.elementSet();
count for "java" tag: tags.count("java");
total count: tags.size();
Impls include ConcurrentHashMultiset, EnumMultiset...
Google Confidential and Proprietary
Next...
Map:
a1
b2
c3
d4
Google Confidential and Proprietary
Multimap<K, V>
Map:
a1
b2
c3
d4
Multimap:
a1
b2
c3
a4
Of course, we often also
want to view this as:
a 1, 4
b2
c3
Google Confidential and Proprietary
Multimap<K, V>
Like a Map (key-value pairs), but may have duplicate keys
The values related to a single key can be viewed as a
collection (set or list)
Consistent design to Map<K, V>
(analogy holds: Map : Set :: Multimap : Multiset)
Typically use instead of a Map<K, Collection<V>>
can view as that type using asMap()
Almost always want variable type to be either
ListMultimap or SetMultimap (and not Multimap)
Implementations include HashMultimap,
ArrayListMultimap...
Not going to say much more about these...
Google Confidential and Proprietary
Immutable Collections
ImmutableSet<Integer> luckyNumbers =
ImmutableSet.of(4, 8, 15, 16, 23, 42);
unlike Collections.unmodifiableXXX, they
perform a copy (not a view / wrapper)
type conveys immutability
offered for all collection types, including JDK ones
inherently thread-safe
deterministic, specified iteration order
reduced memory footprint
slightly improved CPU performance
Prefer immutability!
Google Confidential and Proprietary
FluentIterable<T>
You should all know Iterable<T>:
public interface Iterable<T> {
Iterator<T> iterator();
}
Guava can turn your iterables into fluent iterables:
FluentIterable<Thing> things =
FluentIterable.from(getThings());
... but why? ...
Google Confidential and Proprietary
FluentIterable
Because operations! (note: "lazy")
return FluentIterable.from(database.getClientList())
.filter(
new Predicate<Client>() {
public boolean apply(Client client) {
return client.activeInLastMonth();
}
})
.transform(Functions.toStringFunction())
.limit(10)
.toList();
Google Confidential and Proprietary
FluentIterable API
Chaining methods (return FluentIterable<T>)
filter(Predicate)
transform(Function)
skip(int), limit(int)
cycle()
Query methods (return boolean)
allMatch(Predicate), anyMatch(Predicate)
contains(Object)
isEmpty()
Extraction methods (return Optional<T>)
first(), last(), firstMatch(Predicate), get(int)
Conversion methods (return a copied Collection<T>)
toList(), toSet(), toSortedSet(), toArray()
Google Confidential and Proprietary
Functional Programming
Multiset<Integer> lengths = HashMultiset.create(
FluentIterable.from(strings)
.filter(new Predicate<String>() {
@Override public boolean apply(String s) {
return JAVA_UPPER_CASE.matchesAllOf(s);
}
})
.transform(new Function<String, Integer>() {
@Override public Integer apply(String s) {
return s.length();
}
}));
Google Confidential and Proprietary
w/o Functional Programming
Multiset<Integer> lengths = HashMultiset.create();
for (String s : strings) {
if (UPPER_CASE.matchesAllOf(s)) {
lengths.add(s.length());
}
}
Moral: just be careful out there.
Functional style can be great but it's not automatically the
better way to go.
JDK 8 will make functional programming in Java way better
(JSR-335).
Google Confidential and Proprietary
Comparators
Who loves implementing comparators by hand?
Comparator<String> byReverseOffsetThenName =
new Comparator<String>() {
public int compare(String tzId1, String tzId2) {
int offset1 = getOffsetForTzId(tzId1);
int offset2 = getOffsetForTzId(tzId2);
int result = offset2 - offset1; // careful!
return (result == 0)
? tzId1.compareTo(tzId2)
: result;
}
};
Google Confidential and Proprietary
ComparisonChain example
Here's one way to rewrite this:
Comparator<String> byReverseOffsetThenName =
new Comparator<String>() {
public int compare(String tzId1, String tzId2) {
return ComparisonChain.start()
.compare(getOffset(tzId2), getOffset(tzId1))
.compare(tzId1, tzId2)
.result();
}
};
Never allocates. Short-circuits (kind of).
Google Confidential and Proprietary
Ordering example
Here's another:
Ordering<String> byReverseOffsetThenName =
Ordering.natural()
.reverse()
.onResultOf(tzToOffsetFn())
.compound(Ordering.natural());
// okay, this should actually go above
Function<String, Integer> tzToOffsetFn =
new Function<String, Integer>() {
public Integer apply(String tzId) {
return getOffset(tzId);
}
};
Google Confidential and Proprietary
Ordering details 1/3
Implements Comparator, and adds delicious goodies!
(Could have been called FluentComparator.)
Common ways to get an Ordering to start with:
Ordering.natural()
new Ordering() { public int compare(...) {...} }
Ordering.from(preExistingComparator);
Ordering.explicit("alpha", "beta", "gamma", "delta");
... then ...
Google Confidential and Proprietary
Ordering details 2/3
... then you can use the chaining methods to get an altered
version of that Ordering:
reverse()
compound(Comparator)
onResultOf(Function)
nullsFirst()
nullsLast()
... now you've got your Comparator! But also ...
Google Confidential and Proprietary
Ordering details 3/3
Ordering has some handy operations:
immutableSortedCopy(Iterable)
isOrdered(Iterable)
isStrictlyOrdered(Iterable)
min(Iterable)
max(Iterable)
leastOf(int, Iterable)
greatestOf(int, Iterable)
Google Confidential and Proprietary
... which is better?
Ordering or ComparisonChain?
Answer: it depends, and that's why we have both.
Either is better than writing comparators by hand (why?).
When implementing a Comparator with ComparisonChain,
still extend Ordering anyway!
Google Confidential and Proprietary
Glimpses of other stuff
Google Confidential and Proprietary
Static utils for primitives
Google Confidential and Proprietary
Concurrency libraries
First learn the contents of java.util.concurrent.
Then check out our:
ListenableFuture<V>, ListeningExecutorService
CheckedFuture<V, X>
Service, ServiceManager
RateLimiter
ThreadFactoryBuilder
MoreExecutors
AtomicLongMap<K>
AtomicDouble
Uninterruptibles
...
Google Confidential and Proprietary
Caching
Guava has a powerful on-heap keyvalue cache.
LoadingCache<Key, Graph> cache = CacheBuilder.newBuilder()
.maximumSize(50000)
.expireAfterWrite(33, MINUTES)
.removalListener(notifyMe)
.build(
new CacheLoader<Key, Graph>() {
public Graph load(Key key) throws AnyException {
return createExpensiveGraph(key);
}
});
. . .
return cache.getUnchecked(myKey);
Google Confidential and Proprietary
Unified Hashing API
Object.hashCode() is good enough for in-memory hash
tables. What about more advanced hashing use cases
(fingerprinting, cryptographic, bloom filters...)?
HashCode hash = Hashing.murmur3_128().newHasher()
.putInt(person.getId())
.putString(person.getFirstName())
.putBytes(person.getSomeBytes())
.putObject(person.getPet(), petFunnel)
.hash(); // asLong(), asBytes(), toString()...
You can use murmur3 or JDK-provided algorithms (sha1,
crc32, etc.) with one consistent, user-friendly API.
Google Confidential and Proprietary
Coda
Google Confidential and Proprietary
How to contact us
Need help with a specific problem?
Post to Stack Overflow! Use the "guava" tag.
Report a defect, request an enhancement?
http://code.google.com/p/guava-libraries/issues/entry
Start an email discussion?
Send to
[email protected]Google Confidential and Proprietary
Requesting a new feature
It is hard to sell a new feature to Guava -- even for me!
Your best bet: a really well-documented feature request.
Try to search closed issues first, but don't worry (dups
happen).
1. What are you trying to do?
2. What's the best code you can write to accomplish that
using only today's Guava?
3. What would that same code look like if we added your
feature?
4. How do we know this problem comes up often enough
in real life to belong in Guava?
(Don't rush to code up a patch yet.)
Google Confidential and Proprietary
Q&A
Google Confidential and Proprietary
Some FAQs
... in case you don't ask enough questions!
Google Confidential and Proprietary
1. Y U NO Apache Commons?
Should you use Guava or Apache Commons?
We may be biased, so consult this question on Stack
Overflow:
http://tinyurl.com/guava-vs-apache
Google Confidential and Proprietary
2. Why is Guava monolithic?
Why don't we release separate "guava-collections", "guavaio", "guava-primitives", etc.?
For many usages, binary size isn't an issue.
When it is, a split like this won't actually help! Most users
use a little bit from each package.
Our favorite solution: ProGuard.
A single release is much simpler for us and you.
Google Confidential and Proprietary
3. What about GWT?
A significant subset is available for use with Google Web
Toolkit.
Every class marked @GwtCompatible... minus the
members marked @GwtIncompatible.
Note: We haven't spent much time optimizing for GWT.
Google Confidential and Proprietary
4. What about Android?
Everything should work on Android.
Guava 13.0 requires Gingerbread (has been out 2 years).
Targeting Froyo or earlier? There's a backport, guavajdk5.
Note: We haven't spent much time optimizing for Android.
Google Confidential and Proprietary
5. What is "google-collect"?
Heard of the Google Collections Library 1.0?
It's Guava 0.0, essentially. It's the old name of the project
before we had to rename it to Guava.
So please do not use google-collect.jar! Seek and destroy!
Classpath catastrophe will ensue otherwise!
(More history: if you see a funny version like "guava-r07", it
actually means Guava 7.0. Very sorry!)
Google Confidential and Proprietary
6. Where are fold, reduce, etc?
We're not trying to be the end-all be-all of functional
programming in Java!
We have Predicates and Functions, filter() and transform(),
because we had specific needs for them.
If you code in Java but love the FP ethos, then Java 8 will
be the first thing to really make you happy.
Google Confidential and Proprietary
Thanks!
Google Confidential and Proprietary