The Guava project contains several of Google’s core libraries that we rely on in our Java-based projects: collections, caching, primitives support, concurrency libraries, common annotations, string processing, I/O, and so forth. There will be the slides presenting most useful and interesting features of Guava (v.12) that makes stuff simpler, better and code cleaner. We will cover most of the com.google.common.base.* classes and basic use of functions in collection and Google collections and few other features that are part of Guava and I find them very useful. Some of you will think that there is an overlap with Apache commons – and it’s true, but Guava is built with expectation that there is a Function and a Predicate class as well as various builders which makes it really cool and simple for many use cases.
8. What is Google Guava?
annotations
basic utilities
collections
concurrency
comparison
strings
primitives
ranges
functional idioms
I/o
caching
hashing
event bus
math
reflection
net/http
9. What in this presentation?
annotations
basic utilities
collections
concurrency
comparison
strings
primitives
ranges
functional idioms
I/O
caching
hashing
event bus
math
reflection
net/http
10.
11.
12.
13. Why Guava?
The goal is for you to write less code ...
Make code more readable, cleaner and simpler
Helps developers to focus on business logic rather
than writing java utilities
Saves time, resources and improve productivity
Popular API and active development
Mainstream
Basically... a painkiller and natural extension for Java
18. Guava Releases
About every 3 months, with significant new
functionality and fixes
Release 14.0.1 was released on March 15, 2013
All releases are either major or patch releases
Never minor
26. Joining Strings
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
}
}
27. Joining Strings
Converts collections into single String object
Joining an Iterable, Iterator, varargs/array
Return a String, or append to an Appendable
Throws a NPE on null objects, unless:
.skipNulls()
.useForNull(String)
It also works with Maps
We could be looking at 18 to 48 different methods
30. Splitting Strings
Working in the opposite direction than Joiner
Allows to split String into collection of elements
String.split() on steroids
A better, more intuitive String.split()
Doesn't silently discard trailing separators
Handles empty pieces predictably
31. Splitter
String input = ",, ,apple, orange ,,, banana,, ,guava, ,,";
Iterable<String> split = Splitter.on(',')
.omitEmptyStrings()
.trimResults()
.split(input);
>> [ "apple", "orange", "banana", "guava" ]
The default behavior is simplistic
If you want extra features, ask for them!
32. Splitter
String input = ",, ,apple, orange ,,, banana,, ,guava, ,,";
Iterable<String> split = Splitter.on(',')
.omitEmptyStrings()
.trimResults()
.split(input);
>> [ "apple", "orange", "banana", "guava" ]
The default behavior is simplistic
If you want extra features, ask for them!
By default, assumes nothing about whitespace
These classes use what Googlers (tentatively) call the "Utility Object pattern."
34. CharMatcher
CharMatcher provides many text processing
methods based on “matching character” notation
Separates "configuration" from "processing"
CharMatcher represents two notions:
What constitutes a matching character?
What to do with those matching characters?
Can also be used to "filter" chars
35. CharMatcher (cont.)
Allows to check if a sequence of characters satisfies
given condition:
WHITESPACE, ASCII, ANY, DIGIT (many pre-defined sets)
is('x')
isNot('_')
oneOf("aeiou")
inRange('a', 'z') .or (inRange('A', 'Z')).negate()
36. All that you can do... CharMatcher
Provides methods to modify char sequences:
boolean matchesAllOf(CharSequence)
boolean matchesAnyOf(CharSequence)
boolean matchesNoneOf(CharSequence)
int indexIn(CharSequence, int)
int lastIndexIn(CharSequence, int)
int countIn(CharSequence)
String removeFrom(CharSequence)
String retainFrom(CharSequence)
String trimFrom(CharSequence)
String trimLeadingFrom(CharSequence)
String trimTrailingFrom(CharSequence)
String collapseFrom(CharSequence, char)
String trimAndCollapseFrom(CharSequence, char)
String replaceFrom(CharSequence, char)
42. checkState(boolean)
Throws IllegalStateException if false
Used to check object state
… or…
if (state != State.PLAYABLE) {
throw new IllegalStateException(
"Can't play movie; state is " + state);
}
Preconditions.checkState(state == State.PLAYABLE,
"Can't play movie; state is %s", state);
(what's the difference? none!)
44. checkNotNull(T)
Throws NullPointerException if null
Returns the value. Can be used inline.
. . . with using static import . . .
public Car(Engine engine) {
this.engine = Preconditions.checkNotNull(engine);
}
public Car(Engine engine) {
this.engine = checkNotNull(engine,
“engine cannot be null”);
}
46. Why Preconditions?
Defensive coding
Useful for validation
Each method has three variants:
No extra arguments
An extra object for error message
An extra String & Objects. String.format like
but only allows %s
Recommended to be used as static imports
49. equal(…) & hashCode(…)
public class Person {
private final String name, nickname;
private final Movie favoriteMovie;
@Override
public boolean equals(Object object) {
if (object instanceof Person) {
Person that = (Person) object;
return Objects.equal(this.name, that.name)
&& Objects.equal(this.nickname, that.nickname)
&& Objects.equal(this.favoriteMovie, that.favoriteMovie);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(name, nickname, favoriteMovie);
}
53. Problem with Null
No entry? Or entry exists but the nickname is unlisted?
Person person = personService.findByNickname(“Andy");
if (person == null) {
// what does this mean?
}
54. Problem with Null
No entry? Or entry exists but the nickname is unlisted?
The value in the map is null, or the value is not in the
map. Null can mean failure, can mean success, can
mean almost anything.
Person person = personService.findByNickname(“Andy");
if (person == null) {
// what does this mean?
}
Map.get(key)
55.
56. Optional<T> vs. null
null is "hidden", Optional is ”explicit”
An immutable wrapper that is either:
present: contains a non-null reference
absent: contains nothing
Note that it never "contains null"
Possible uses:
return type
“a T that must be present"
"a T that might be absent"
distinguish between
"unknown" (for example, not present in a map)
"known to have no value" (present in the map, with value
Optional.absent())
wrap nullable references for storage in a collection that does
not support null
57. Optional<T>
// Make optional of given type
Optional<String> possible = Optional.of(“Ido”);
Optional<String> value = Optional.fromNullable(str);
if (value.isPresent()) {
// ...
}
// returns true if nonNull
possible.isPresent();
// returns this possible value or default
possible.or(“Nick”);
// returns Ido
possible.get();
58. Making an Optional
Optional.of(T) - make optional of given non-null
value or fail fast on null
Optional.absent() - return an absent optional of
some type
Optional.fromNullable(T) - turn value in
Optional and treat null as absent
59. 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!
60. Others… Strings
Methods are primarily for interfacing with
unpleasant APIs that equate null strings and empty
strings:
Strings.emptyToNull(String)
Strings.isNullOrEmpty(String)
Strings.nullToEmpty(String)
63. StopWatch
Class for measuring elapsed time
Prefer StopWatch over System.nanoTime()
Don't use System.currentTimeMillis()!
Provides methods that automatically calculate time
between start() and stop() execution
65. StopWatch Pros
StopWatch uses nanoTime() but exposes only relative
timings, a meaningless absolute value
Alternate time sources can be substituted using Ticker
(read() returns nanoseconds)
Can be easily mocked with custom passing time provider
Returns counted time using different units
toString() gives human readable format
66. Functional Concepts brought to Java
Many things in Guava are inspired by functional
concepts from other programming languages
In Java can only be approximated through awkward
and verbose use of anonymous classes
Expected to change in Java 8
Guava is currently aimed at users of Java 5 and
above
68. Core concepts
Key functional concepts Guava uses:
Function<F, T> == F => T
=> to transform a collection
public interface Function<F, T> {
@Nullable T apply(@Nullable F input);
}
69. Core concepts
Key functional concepts Guava uses:
Function<F, T> == F => T
=> to transform a collection
Predicate<T> == T => Boolean
=> filter out a collection
public interface Function<F, T> {
@Nullable T apply(@Nullable F input);
}
public interface Predicate<T> {
boolean apply(@Nullable T input);
}
72. Function <F,T>
Java 7 doesn't have lambda expressions, but Guava
helps us out (a bit) with Function
public void demo(Collection<String> input) {
Function<String, String> toUpperCase =
new Function<String, String>() {
@Override
public String apply(String string) {
return string.toUpperCase();
}
};
Collection<String> transformed =
Collections2.transform(input, toUpperCase);
}
73. Predicate<T> usage
Predicate checks if condition is met for passed object
Tools to manipulate collections using Predicate:
FluentIterables.filter()
Iterables.filter()
Iterators.filter()
Collections2.filter()
Sets.filter()
Maps, MultiMaps, … etc.
74. Predicate <T>
Quite similar to Function but does NOT extend it
Predicate<User> onlyAwesome = new Predicate<User>() {
@Override
public boolean apply(User in) {
return Optional.fromNullable(in)
.or(User.NOT_AWESOME).isAwesome();
}
};
75. Predicate <T>
Let's use it on a collection:
Iterable<User> users = getMixedUsers();
// find all awesome users
Iterable<User> onlyAwesomeUsers = Iterables.filter(users, onlyAwesome);
// find one (first) awesome user
User awesomeUser = Iterables.find(users, onlyAwesome);
// or better
Optional<User> awesomeOrAbsent = Iterables.tryFind(users, onlyAwesome);
76. Putting it together
private Iterable<Integer> puttingItTogether(Iterable<Integer> numbers)
{
FluentIterable<Integer> squaresOfEvens =
FluentIterable.from(numbers)
.filter(new Predicate<Integer>() {
@Override
public boolean apply(Integer input) {
checkNotNull(input, "nulls are not allowed here!");
return input % 2 == 0;
}}).transform(new Function<Integer, Integer>() {
@Override
public Integer apply(Integer input) {
checkNotNull(input, "nulls are not allowed here!");
return input * input;
}
});
return squaresOfEvens;
}
77. … Or
List<Integer> squaresOfEvens = Lists.newArrayList();
for (Integer number : givenNumbers) {
if (number % 2 == 0) {
squaresOfEvens.add(number * number);
}
}
>> [ 4, 16, 36, 64, 100 ]
78. … Moral
List<Integer> squaresOfEvens = Lists.newArrayList();
for (Integer number : givenNumbers) {
if (number % 2 == 0) {
squaresOfEvens.add(number * number);
}
}
>> [ 4, 16, 36, 64, 100 ]
Just be careful!!
Functional style can be great but it's not
automatically the better way to go.
81. Java Caching with Guava
Guava has a powerful on-heap key→value cache
Thread-safe implementation
More or less internally similar to ConcurrentMap +
automatic eviction
No explicit support for distributed caching
82. Types of Caches
Provides two types of caches:
LoadingCache - knows how to load entries when
a cache miss occurs
LoadingCache.get(key) returns the value associated with
key, loading it first if necessary
Cache - does not automatically load entries
We're going to focus on the loading case here; it's
usually what you want
84. CacheBuilder
The CacheBuilder has next properties:
Cache size
Time to expire entries after last access
Time based expiration of entries after being updated
Use of weak or soft references for keys/values
Setting RemovalListener that can receive events once
an entry is removed fro the cache.
Concurrency level for update operations (defaults to 4)
Enable recording caching stats
86. Concurrency
Cache instances are internally implemented very
similar to ConcurrentHashMap (thus thread-safe)
CacheLoader.load will be invoked a single time for
each key, regardless of the number of requesting
threads
The result will be returned to all requesting
threads and inserted into the cache using the
equivalent of putIfAbsent
87. Cache Eviction
By size
.maximumSize(long)
By custom weight:
.weigher(Weigher)
.maximumWeight(long)
By time:
.expireAfterAccess(long, TimeUnit)
.expireAfterWrite(long, TimeUnit)
89. Checked Exceptions
What if loading causes a checked exception?
CacheLoader<String, String> checkedLoader =
new CacheLoader<String, String>() {
@Override
public String load(String key) throws IOException {
return loadFromDisk(key);
}
};
90. Checked Exceptions (cont.)
LoadingCache<String, String> cache =
CacheBuilder.newBuilder().build(checkedLoader);
try {
cache.get(key);
} catch (ExecutionException e) {
// ensure stack trace is for this thread
throw new IOException(e.getCause());
}
91. Cache Stats
hitCount – number of times Cache returned the
cached value
missCount – number of times Cache returned
uncached value
loadSuccessCount – number of times Cache
loaded new value successfully
95. 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<E> implementation only needs to
store one occurrence of each element, plus a count!
[a x 3, c x 2, b x 3]
96. MultiSet<E>
Add multiple instances of a given element
Counts how many occurrences exist
Similar to a Map<E, Integer>, but...
only positive counts
size() returns total # of items, not # keys
count() for a non-existent key is 0
iterator() goes over each element
Usage: i.e. Track frequencies of elements, e.g. "word
counting"
101. MultiMap<K, V>
Like Map (key-value pairs), but may have duplicates
The values related to a single key can be viewed as a
collection (set or list)
Similar to a Map<K, Collection<V>>, but...
get() never returns null (returns an empty collection)
containsKey() is true only if 1 or more values exist
entries() returns all entries for all keys
size() returns total number of entries, not keys
asMap() to view it as a Map<K, Collection<V>>
104. BiMap<K1, K2>
Bi-directional Map
Both keys and values are unique
Can view the inverse map with inverse()
Use instead of maintaining two separate
maps:
Map<K1, K2>
Map<K2, K1>
105. Static utilities
In classes with name ending with an s
Lists
Maps
Multimaps
Multisets
Sets
SortedMaps
Tables
Iterators
Iterables
Collections2
106. Static factories methods
Rather than typing
you type
Map<String, Class<? extends Handler>> m =
new HashMap<String, Class<? extends Handler>>();
Map<String, Class<? extends Handler>> m2 = Maps.newHashMap();
107. Guava Alternatives
Should you use Guava or Apache Commons?
We may be biased, so consult this question on Stack
Overflow:
http://tinyurl.com/guava-vs-apache
The large number of upvotes for the top answers
shows a pretty strong community consensus
108. Need help with a problem?
Post to Stack Overflow! Use the "guava" tag
Report a defect, request an enhancement?
http://code.google.com/p/guava-libraries/issues/list
Start an email discussion?
Send to guava-discuss@googlegroups.com
General discussion takes place on
http://groups.google.com/group/guava-discuss
The Guava team is generally highly active in all of
these areas
CacheBuilder.weakKeys() stores keys using weak references. This allows entries to be garbage-collected if there are no other (strong or soft) references to the keys. Since garbage collection depends only on identity equality, this causes the whole cache to use identity (==) equality to compare keys, instead of equals().CacheBuilder.weakValues() stores values using weak references. This allows entries to be garbage-collected if there are no other (strong or soft) references to the values. Since garbage collection depends only on identity equality, this causes the whole cache to use identity (==) equality to compare values, instead of equals().CacheBuilder.softValues() wraps values in soft references. Softly referenced objects are garbage-collected in a globally least-recently-used manner, in response to memory demand. Because of the performance implications of using soft references, we generally recommend using the more predictable maximum cache size instead. Use of softValues() will cause values to be compared using identity (==) equality instead of equals().