google guava for cleaner code
DESCRIPTION
Presentation on JugMK eventTRANSCRIPT
Cleaner code with Guava
08-02-2012
@mitemitreski
Code samples @ git://github.com/mitemitreski/guava-examples.git
What is Guava?
What is Google Guava?
• com.google.common.annotation• com.google.common.base• com.google.common.collect• com.google.common.io• com.google.common.net• com.google.common.primitives• com.google.common.util.concurrent
NULL
"Null sucks." - Doug Lea
"I call it my billion-dollar mistake." - C. A. R. Hoare
if ( x != null && x.someM()!=null && ) {}
Null is ambiguous
@Test
public void optionalExample() {
Optional<Integer> possible = Optional.of(3);// Make optional of given type
possible.isPresent(); // returns true if nonNull
possible.or(10); // returns this possible value or default
possible.get(); // returns 3
}
@Test
public void testNeverNullWithoutGuava() {
Integer defaultId = null;
Integer id = theUnknowMan.getId() != null ? theUnknowMan.getId() : defaultId;
}
@Test(expected = NullPointerException.class)
public void testNeverNullWithGuava() {
Integer defaultId = null;
int id = Objects.firstNonNull(theUnknowMan.getId(), defaultId);
assertEquals(0, id);
}
// all in (expression, format,message)
public void somePreconditions() {
checkNotNull(theUnknowMan.getId()); // Will throw NPE
checkState(!theUnknowMan.isSick()); // Will throw IllegalStateException
checkArgument(theUnknowMan.getAddress() != null,
"We couldn't find the description for customer with id %s", theUnknowMan.getId());
}
JSR-305 Annotations for software defect detection
@Nullable @NotNull
1.javax.validation.constraints.NotNull - EE6
2.edu.umd.cs.findbugs.annotations.NonNull – Findbugs, Sonar
3.javax.annotation.Nonnull – JSR-305
4.com.intellij.annotations.NotNull - intelliJIDEA
What to use and when?
Eclipse support
hashCode() and equals()
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((adress == null) ? 0 : adress.hashCode()); result = prime * result + ((id == null) ? 0 : id.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((url == null) ? 0 : url.hashCode()); return result; }
hashCode() and equals()
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((adress == null) ? 0 : adress.hashCode()); result = prime * result + ((id == null) ? 0 : id.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((url == null) ? 0 : url.hashCode()); return result; }
The Guava way
Objects.equal("a", "a"); //returns trueObjects.equal(null, "a"); //returns falseObjects.equal("a", null); //returns falseObjects.equal(null, null); //returns true
Object.equals(Object a, Object b)
Object.deepEquals(Object a, Object b)
JDK7
Objects.hashCode(name,adress,url);
Objects.hash(name,adress,url);
Objects.toStringHelper(this) .add("x", 1) .toString();
The Guava way
public int compareTo(Foo that) { return ComparisonChain.start() .compare(this.aString, that.aString) .compare(this.anInt, that.anInt) .compare(this.anEnum, that.anEnum, Ordering.natural().nullsLast()) .result(); }
Common Primitives
Joiner/ Splitter
Character Matchers
Use a predefined constant (examples)• CharMatcher.WHITESPACE (tracks Unicode defn.)• CharMatcher.JAVA_DIGIT• CharMatcher.ASCII• CharMatcher.ANY
Use a factory method (examples)• CharMatcher.is('x')• CharMatcher.isNot('_')• CharMatcher.oneOf("aeiou").negate()• CharMatcher.inRange('a', 'z').or(inRange('A',
'Z'))
Character Matchers
String noControl = CharMatcher.JAVA_ISO_CONTROL.removeFrom(string); // remove control charactersString theDigits = CharMatcher.DIGIT.retainFrom(string); // only the digitsString lowerAndDigit = CharMatcher.or(CharMatcher.JAVA_DIGIT, CharMatcher.JAVA_LOWER_CASE).retainFrom(string); // eliminate all characters that aren't digits or lowercase
import com.google.common.cache.*;
Cache<Integer, Customer> cache = CacheBuilder.newBuilder() .weakKeys() .maximumSize(10000) .expireAfterWrite(10, TimeUnit.MINUTES) .build(new CacheLoader<Integer, Customer>() {
@Override public Customer load(Integer key) throws Exception {
return retreveCustomerForKey(key); }
});
import com.google.common.collect.*;
• Immutable Collections• Multimaps, Multisets, BiMaps… aka Google-
Collections• Comparator-related utilities• Stuff similar to Apache commons collections• Some functional programming support
(filter/transform/etc.)
Functions and Predicates
Java 8 will support closures …
Function<String, Integer> lengthFunction = new Function<String, Integer>() { public Integer apply(String string) { return string.length(); }};Predicate<String> allCaps = new Predicate<String>() { public boolean apply(String string) { return CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string); }};
It is not recommended to overuse this!!!
Filter collections
@Test public void filterAwayNullMapValues() { SortedMap<String, String> map = new TreeMap<String, String>(); map.put("1", "one"); map.put("2", "two"); map.put("3", null); map.put("4", "four"); SortedMap<String, String> filtered = SortedMaps.filterValues(map, Predicates.notNull()); assertThat(filtered.size(), is(3)); // null entry for "3" is gone! }
Filter collectionsCollection type Filter method
Iterable Iterables.filter(Iterable, Predicate)
Iterator Iterators.filter(Iterator, Predicate)
Collection Collections2.filter(Collection, Predicate)
Set Sets.filter(Set, Predicate)
SortedSet Sets.filter(SortedSet, Predicate)
Map Maps.filterKeys(Map, Predicate) Maps.filterValues(Map, Predicate)Maps.filterEntries(Map, Predicate)
SortedMap Maps.filterKeys(SortedMap, Predicate)Maps.filterValues(SortedMap, Predicate)Maps.filterEntries(SortedMap, Predicate)
Multimap Multimaps.filterKeys(Multimap, Predicate)Multimaps.filterValues(Multimap, Predicate)Multimaps.filterEntries(Multimap, Predicate)
Iterables Signature
boolean all(Iterable, Predicate)
boolean any(Iterable, Predicate)
T find(Iterable, Predicate)
removeIf(Iterable, Predicate)
Transform collectionsListMultimap<String, String> firstNameToLastNames;// maps first names to all last names of people with that first name
ListMultimap<String, String> firstNameToName = Multimaps.transformEntries(firstNameToLastNames, new EntryTransformer<String, String, String> () { public String transformEntry(String firstName, String lastName) { return firstName + " " + lastName; } });
Transform collections
Collection type Transform method
Iterable Iterables.transform(Iterable, Function)
Iterator Iterators.transform(Iterator, Function)
Collection Collections2.transform(Collection, Function)
List Lists.transform(List, Function)
Map* Maps.transformValues(Map, Function) Maps.transformEntries(Map, EntryTransformer)
SortedMap* Maps.transformValues(SortedMap, Function)Maps.transformEntries(SortedMap, EntryTransformer)
Multimap* Multimaps.transformValues(Multimap, Function)Multimaps.transformEntries(Multimap, EntryTransformer)
ListMultimap* Multimaps.transformValues(ListMultimap, Function)
Multimaps.transformEntries(ListMultimap, EntryTransformer)
Table Tables.transformValues(Table, Function)
Collection goodies
// oldway Map<String, Map<Long, List<String>>> mapOld = new HashMap<String, Map<Long, List<String>>>(); // the guava way Map<String, Map<Long, List<String>>> map = Maps.newHashMap(); // list ImmutableList<String> of = ImmutableList.of("a", "b", "c"); // Same one for map ImmutableMap<String, String> map = ImmutableMap.of("key1", "value1", "key2", "value2"); //list of ints List<Integer> theList = Ints.asList(1, 2, 3, 4, 522, 5, 6);
Load resources
When to use Guava?
• Temporary collections
• Mutable collections
• String Utils
• Check if (x==null)
• Always ?
When to use Guava?
"I could just write that myself." But...
•These things are much easier to mess up than it seems
•With a library, other people will make your code faster for You
•When you use a popular library, your code is in the
mainstream
•When you find an improvement to your private library, how
many people did you help?
Well argued in Effective Java 2e, Item 47.
Where can you use it ?
•Java 5.0+
• GWT
•Android
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>10.0.1</version></dependency>