An Overview of Guava: Google Core Libraries For Java
An Overview of Guava: Google Core Libraries For Java
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
com.google.common.base
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
}
}
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
Splitter
Similar! But in the other direction.
return Splitter.on("|")
.omitEmptyStrings()
.split("|Harry||Ron|||Hermione
// returns "Harry", "Ron", "Hermione
||");
";
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...
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".
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
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
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
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!
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
Preconditions
Objects.toStringHelper()
Objects.firstNonNull(T, T)
Throwables.propagate(Throwable)
CaseFormat
Strings.repeat(String, int)
Equivalence<T>
Function, Predicate, Supplier
com.google.common.collect
Ordered?
Y
N
+------------+----------+
Y |
List
|
?
|
Dups?
+------------+----------+
N |
?
|
Set
|
+------------+----------+
Ordered?
Y
N
+------------+----------+
Y |
List
| Multiset |
Dups?
+------------+----------+
N |(UniqueList)|
Set
|
+------------+----------+
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]
Next...
Map:
a1
b2
c3
d4
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
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? ...
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();
}
}));
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;
}
};
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();
}
};
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);
}
};
reverse()
compound(Comparator)
onResultOf(Function)
nullsFirst()
nullsLast()
immutableSortedCopy(Iterable)
isOrdered(Iterable)
isStrictlyOrdered(Iterable)
min(Iterable)
max(Iterable)
leastOf(int, Iterable)
greatestOf(int, Iterable)
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);
Coda
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
Q&A
Some FAQs
... in case you don't ask enough questions!
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
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!)
Thanks!