View
4.873
Download
5
Category
Tags:
Preview:
DESCRIPTION
Citation preview
Google Guava
2011/04/26
EclipseModelingFramework
&
Mikaël Barbero
Introduction
1http://www.flickr.com/photos/drspam/295023450/
About me
‣ Modeling consultant‣ Research engineer‣ Trainer‣ Conference Speaker‣ Language guy ;)
‣ Eclipse committer‣ Guava-OSGi packager‣ EMFPath lead
Nantes
Paris
Strategic members
AcceleoEMFCompareATLGMFOCLMylyn IntentEEFSTP
Leading
Available technologies
GuavaOverview
2http://www.flickr.com/photos/slowburn/2986303105/
http://www.flickr.com/photos/awagnon/1626025855/
Java library used internally @
Google for years
Superset of Google
Collections
About Guava
About Guava
Apache License v2http://www.apache.org/licenses/LICENSE-2.0
About Guava
2007 2008 2009 2010 2011
Google Collec
tions
v0.5
Google Collec
tions
v1Guava
r03
Guava r0
8
Frequent releases (quarterly base)Latest release (r09): April, 7th
Why using Guava?
Simplexity
http://www.flickr.com/photos/gio_vencato/4941064345/
Why using Guava?
http://www.flickr.com/photos/reway2007/3300379295/
Why using Guava?
http://www.flickr.com/photos/funtik/1175522045/
Mainstream?
Why using Guava?
Helping others
http://www.flickr.com/photos/thearches/4381959041/
IO Networking Concurrency
Primitive types Collections
Inside Guava
GWT compatibility is tested (see @GwtCompatible)
Comparison withApache Commons
http://stackoverflow.com/questions/4542550/what-are-the-big-improvements-between-guava-and-apache-equivalent-libraries
More ModernBetter
DesignedBetter
Supported
Java 5
Respects JDK contracts
Best practices and patterns
Orthogonality (@Beta to test designs)
Actively developed
(- commons 3.0)
Google depends on it
(e.g., Google Guice)
Bestrep.
Corest of the core
3http://www.flickr.com/photos/27384147@N02/5211738745/
public class Person { final String name, nickname; final Movie favMovie;
@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.favMovie, that.favMovie); } return false; }
@Override public int hashCode() { return Objects.hashCode(name, nickname, favMovie); }}
Objects class
Example from http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
public class Person { final String name, nickname; final Movie favMovie;
//...
@Override public String toString() { return Objects.toStringHelper(this) .add("name", name) .add("nickname", nickname) .add("favMovie", favMovie) .toString(); }
public String preferredName() { return Objects.firstNonNull(nickname, name); }}
Objects class
Example from http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
Preconditions
Defensive coding
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);
Example from http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
Preconditions
Defensive coding
public void setRating(StarRating rating) { if (rating == null) { throw new NullPointerException(); } this.rating = rating;}
public void setRating(StarRating rating) { this.rating = checkNotNull(rating);}
Example from http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
Equivalences strategies
public interface Equivalence<T> { boolean equivalent(@Nullable T a, @Nullable T b); int hash(@Nullable T t);}
Equivalence equals = Equivalences.equals();Equivalence identity = Equivalences.identity();
Equivalence<String> elementEquivalence = ...;Equivalence<Iterable<String>> pairwise = Equivalences.pairwise(elementEquivalence);Collection<String> c1, c2;pairwise.equivalent(c1, c2);
Suppliers
public interface Supplier<T> { T get();}
Supplier<String> s = ...;Supplier<String> memoizing = Suppliers.memoize(s);Supplier<String> expiring = Suppliers.memoizeWithExpiration(s, 100, TimeUnit.SECONDS);Supplier<String> ofInstance = Suppliers.ofInstance("Always returning");
Throwables
Throwables.getCausalChain(throwable);Throwables.getRootCause(throwable);
Throwables.getStackTraceAsString(throwable);
Throwables.propagateIfInstanceOf(throwable, IOException.class);
Throwables.propagateIfPossible(throwable);
try { someMethodThatCouldThrowAnything();} catch (IKnowWhatToDoWithThisException e) { handle(e);} catch (Throwable t) { Throwables.propagateIfPossible(t); throw new RuntimeException("unexpected", t);}
@Annotation
@Beta
@GwtCompatible @GwtIncompatible
@VisibleForTesting
Strings
4http://www.flickr.com/photos/gernot/2554175292/
http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
CharMatcher
StringUtil example: allAscii, collapse, collapseControlChars, collapseWhitespace, indexOfChars, lastIndexNotOf, numSharedChars, removeChars, removeCrLf, replaceChars, retainAllChars, strip, stripAndCollapse, stripNonDigits, ...
Partial cross product of two notions: (a) what's a "matching" character?
(b) what to do with those matching characters?
CharMatcher:An instance of this type represents part (a), and the operation you invoke on it represents part (b).
+1
Getting a CharMatcher
CharMatcher.is('x') CharMatcher.isNot('_') CharMatcher.oneOf("aeiou").negate() CharMatcher.inRange('a', 'z').or(inRange('A', 'Z'))
Subclass CharMatcher, implement matches(char c)
CharMatcher.WHITESPACE (Unicode) CharMatcher.JAVA_DIGIT CharMatcher.ASCIICharMatcher.ANY
Factory methods (examples)
Predefined constants(examples)
Now check out all that you can do...http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
‣ 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)
Using your CharMatcher
http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
Using your CharMatcher
http://scaramoche.blogspot.com/2010/05/googles-guava-library-tutorial-part-1.html
String string = "Scream 4";CharMatcher matcher = CharMatcher.JAVA_LETTER_OR_DIGIT;int count = matcher.countIn(string);
System.out.println("Letter or digit count: "+count);// Letter or digit count: 7
System.out.println(matcher.matchesAllOf("scream"));// true
System.out.println(matcher.matchesAllOf("scream "));// false
System.out.println(matcher.matchesNoneOf("_?=)("));// true
Splitter
‣ regular expression ‣ result as an array ‣ its way of handling empty pieces (which is very strange)
http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
",a,,b,".split(",") returns...(a) "", "a", "", "b", "" (b) null, "a", null, "b", null (c) "a", null, "b" (d) "a", "b" (e) None of the above
Mini-puzzler
+1
JDK has splitter
Splitter
http://www.flickr.com/photos/terence_s_jones/5060802981/
Splitter is String.split() on steroidshttp://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
Splitter
http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
The default behavior is simplistic:
//yields [" foo", " ", "bar", " quux", ""] Splitter.on(',').split(" foo, ,bar, quux,");
//yields ["foo", "bar", "quux"] Splitter.on(',') .trimResults() .omitEmptyStrings() .split(" foo, ,bar, quux,");
If you want extra features, ask for them!
Ascii, CharsetsAscii
‣Charsets.ISO_8859_1;‣Charsets.US_ASCII;‣Charsets.UTF_16;‣Charsets.UTF_16BE; ‣Charsets.UTF_16LE;‣Charsets.UTF_8;
list of bytes constants for each Char between 0x00 & 0x7F
Charsets
Guaranteed to be supported by
all Java platform implementations
try { bytes = string.getBytes("UTF-8");} catch (UnsupportedEncodingException e) { // how can this possibly happen? throw new AssertionError(e);}
No more
Strings
boolean b = Strings.isNullOrEmpty(s);
String str = Strings.emptyToNull(s);
String str = Strings.nullToEmpty(s);
CaseFormat
‣ LOWER_CAMEL ‣ Java variable naming convention, e.g., "lowerCamel".
‣ LOWER_HYPHEN‣ Hyphenated variable naming convention, e.g., "lower-hyphen".
‣ LOWER_UNDERSCORE ‣ C++ variable naming convention, e.g., "lower_underscore".
‣ UPPER_CAMEL ‣ Java and C++ class naming convention, e.g., "UpperCamel".
‣ UPPER_UNDERSCORE ‣ Java and C++ constant naming convention, e.g., "UPPER_UNDERSCORE".
CaseFormat.to(CaseFormat.UPPER_UNDERSCORE, s);Example
Collections
5http://www.flickr.com/photos/tochis/1169807846/
Ordering
Comparator is easy to implement, but a pain to use
Push the Comparator<T> interface to the next level
http://scaramoche.blogspot.com/2010/05/googles-guava-library-tutorial-part-2.html
public interface Comparator<T> {
abstract int compare(T, T);
abstract boolean equals(Object);
}
public class Employee implements Comparable<Employee> { private final int id; private final String name; private final int yearsOfService;
public Employee(int id, String name, int yearsOfService) { this.id = id; this.name = name; this.yearsOfService = yearsOfService; }
public int getId() { return id; }
public String getName() { return name; }
public int getYearsOfService() { return yearsOfService; }
@Override public int compareTo(Employee employee) { return this.getName().compareTo(employee.getName()); }
@Override public String toString() { return Objects.toStringHelper(this) .add("id", id) .add("name", name) .add("years of service", yearsOfService) .toString(); }}
http://scaramoche.blogspot.com/2010/05/googles-guava-library-tutorial-part-2.html
Simple data class
Ordering
Ordering
Employee anakinSk = new Employee(4, "Anakin Skywalker", 4);Employee darthVader = new Employee(3, "Darth Vader", 5);Employee hanSolo = new Employee(2, "Han Solo", 10);List <Employee> employeeList = Lists.newArrayList(anakinSk, hanSolo, darthVader);System.out.println("employee list: "+employeeList);
employee list: [Employee{id=4, name=Anakin Skywalker, years of service=4}, Employee{id=2, name=Han Solo, years of service=10}, Employee{id=3, name=Darth Vader, years of service=5}]
http://scaramoche.blogspot.com/2010/05/googles-guava-library-tutorial-part-2.html
Ordering
Comparator<Employee> yearsComparator = new Comparator<Employee>() { @Override public int compare(Employee employee1, Employee employee2) { return (employee1.getYearsOfService() - employee2 .getYearsOfService()); }};
Comparator<Employee> idComparator = new Comparator<Employee>() { @Override public int compare(Employee employee1, Employee employee2) { return (employee1.getId() - employee2.getId()); }};
Define your own Comparator
http://scaramoche.blogspot.com/2010/05/googles-guava-library-tutorial-part-2.html
Ordering
Ordering<Employee> orderUsingYearsComparator = Ordering.from(yearsComparator);
Create an Ordering from a Comparator
List<Employee> sortedCopy = orderUsingYearsComparator.sortedCopy(employeeList);System.out.println("sorted copy: " + sortedCopy);
Use your ordering, e.g. to sort
sorted copy: [Employee{id=4, name=Anakin Skywalker, years of service=4}, Employee{id=3, name=Darth Vader, years of service=5}, Employee{id=2, name=Han Solo, years of service=10}]
http://scaramoche.blogspot.com/2010/05/googles-guava-library-tutorial-part-2.html
Ordering
toString() ordering
Ordering<Object> toStringOrdering = Ordering.usingToString();
Ordering<Employee> natural = Ordering.natural();
Natural ordering (Comparable<T>)
http://scaramoche.blogspot.com/2010/05/googles-guava-library-tutorial-part-2.html
What you can do with Ordering
‣ Ordering.min(Iterable<E>) ‣ Ordering.max(Iterable<E>)‣ Ordering.leastOf(Iterable<E>, int)‣ Ordering.greatestOf(Iterable<E>, int)
‣ Ordering.isOrdered(Iterable<? extends T>)‣ Ordering.isStrictlyOrdered(Iterable<? extends T>)
‣ Ordering.binarySearch(List<? extends T>, T)
What you can do with Ordering
‣ Ordering.sortedCopy(Iterable<E>)‣ Ordering.immutableSortedCopy(Iterable<E>)
Better than new TreeSet(Collection)
Do not discard duplicates elements
Performed sort is stable
Ordering is configurable
‣ Ordering.reverse()‣ Ordering.lexicographical()‣ Ordering.nullsFirst()‣ Ordering.nullsLast()‣ Ordering.reverse()
[] < [1] < [1, 1] < [1, 2] < [2]
Lexicographical returns an Ordering on Iterable of T
ObjectArrays
‣ concat(T, T[])
‣ concat(T[], T)
‣ concat(T[], T[], Class<T>)
‣ newArray(Class<T>, int)
‣ newArray(T[], int)
Multiset & Multimap
Historically, multisets (aka bags) and multimaps emulated atop maps
Multimap = Map<K, List<V>>
Multiset = Map<K, Integer>
When to use Multiset?
‣"I kinda want a Set except I can have duplicates"‣ card games example‣ changing to List sacrifices contains() performance ‣"Are these Lists equal, ignoring order?"‣ write a utility method for this? Histograms
‣"What distinct tags am I using on my blog, and how many times do I use each one?"
Multiset performance varies by the number
of distinct elements, not total size.
http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf
Map<String, Integer> tags = new HashMap<String, Integer>();for (BlogPost post : getAllBlogPosts()) { for (String tag : post.getTags()) {
int value = tags.containsKey(tag) ? tags.get(tag) : 0; tags.put(tag, value + 1);
}}
Multiset
distinct tags: tags.keySet()
count for "java" tag: tags.containsKey("java") ? tags.get("java") : 0;
total count: // oh crap...
http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf
Ever done this?
Usage
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();
http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf
Would you rather do this?
Usage(hurrah)
‣What if you need to remove/decrement?‣Don't accidentally go negative ‣Don't forget to prune! ‣(Or just use a Multiset.)
‣What about concurrency? ‣Lock the entire map just to add one tag? ‣(Or just use our ConcurrentMultiset.)
Multiset API
http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf
When you use a powerful library, your code can easily evolve.
Multiset API
‣int count(Object element);
‣int add(E element, int occurrences);
‣boolean remove(Object element, int occurrences);
‣int setCount(E element, int newCount);
‣boolean setCount(E e, int oldCount, int newCount);
http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf
Multiset implementations
ImmutableMultisetHashMultisetLinkedHashMultisetTreeMultisetEnumMultisetConcurrentHashMultiset
http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf
+1
When to use Multimap?
Map<Salesperson, List<Sale>> map = new HashMap<Salesperson, List<Sale>>();public void makeSale(Salesperson salesPerson, Sale sale) { List<Sale> sales = map.get(salesPerson); if (sales == null) { sales = new ArrayList<Sale>(); map.put(salesPerson, sales); } sales.add(sale);}
http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf
Ever done this?
When to use Multimap?
The code on the previous slide is ‣Verbose‣Bug-prone ‣Limited in functionality ‣Using the wrong abstraction
http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf
Multimap<Salesperson, Sale> multimap = ArrayListMultimap.create();public void makeSale(Salesperson salesPerson, Sale sale) { multimap.put(salesPerson, sale);}
Would you rather do this?
More about MultimapA collection of key-value pairs (entries), like a Map,
except that keys don't have to be unique.
{a=1, a=2, b=3, c=4, c=5, c=6}
multimap.get(key) returns a modifiable Collection view of the values associated with that key.
Sometimes you want to think of it as a Map<K, Collection<V>> -- use the asMap() view:
{a=[1, 2], b=[3], c=[4, 5, 6]}http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf
Multimap subtypes
‣ListMultimap: the get() view implements List‣preserves the ordering of entries per key; ‣can have duplicate entries
‣SetMultimap: the get() view implements Set‣no duplicate entries, ‣ordering of entries is impl-dependent
‣SortedSetMultimap: the get() view implements SortedSet‣you get the idea
http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf
Hmm... sounds a lot like a plain old Map<K, Collection<V>>? But wait...
Multimap, before
public Sale getBiggestSale() { Sale biggestSale = null; for (List<Sale> sales : map.values()) { Sale myBiggestSale = Collections.max(
sales, SALE_CHARGE_COMPARATOR);
if (biggestSale == null || myBiggestSale.getCharge() > biggestSale().getCharge()) { biggestSale = myBiggestSale; } } return biggestSale;}
Now we want to find the biggest Sale.
Without Multimap:
http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf
Multimap, after
Multimap has six: ‣get(), ‣keys(), ‣keySet(), ‣values(), ‣entries(), ‣asMap().
public Sale getBiggestSale() { return Collections.max(multimap.values(), SALE_CHARGE_COMPARATOR);}
http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf
View collections are very powerful.
Multimap APIMost Map methods are identical on Multimap:‣ size(), ‣ isEmpty(),‣ containsKey(), ‣ containsValue(),‣ put(), ‣ putAll(),‣ clear(),‣ values()
The others have analogues:‣ get() returns Collection<V> instead of V ‣ remove(K) becomes remove(K,V) and removeAll(K) ‣ keySet() becomes keys() (well, and keySet()) ‣ entrySet() becomes entries()
And Multimap has a few new things:‣ containsEntry(), ‣ replaceValues()
http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf
Multimap implementations
ImmutableMultimapImmutableListMultimapImmutableSetMultimap
ArrayListMultimapHashMultimap
LinkedHashMultimapLinkedListMultimap
TreeMultimap
http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf
ListMultimapSetMultimap
SortedSetMultimap
+1
BiMap
aka unique-valued mapvalues are unique, as well as its keys
Has an inverse() view, which is another BiMapbimap.inverse().inverse() == bimap
http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf
Stop creating two separate
forward and backward Maps!
+1
BiMap Implementations
ImmutableBiMap HashBiMap EnumBiMapEnumHashBiMap
http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf
Constrained Collections/Maps
//...public Object checkElement(Object element) { if (element == null) { throw new NullPointerException(); } return element;}//...
public interface Constraint<E> { E checkElement(E element);}
Constraints.notNull()
Constrained Collections/Maps
constrainedCollection(Collection<E>, Constraint<? super E>)
constrainedList(List<E>, Constraint<? super E>)
constrainedMultiset(Multiset<E>, Constraint<? super E>)
constrainedSet(Set<E>, Constraint<? super E>)
constrainedSortedSet(SortedSet<E>, Constraint<? super E>)
Constraints.
MapMaker
A ConcurrentMap builder, providing any combination of these features:‣Soft or weak keys‣Soft or weak values‣Timed expiration‣On-demand computation of values
Far more powerful, easy to use than WeakHashMap
Concurrent on-demand computation is really hard
+1
MapMaker
ConcurrentMap<User, Graph> recommendations = new MapMaker()
.concurrencyLevel(4) .softKeys()
.weakValues()
.maximumSize(10000) .expireAfterWrite(10, TimeUnit.MINUTES) .makeComputingMap( new Function<User, Graph>() { public Graph apply(User user) { return createExpensiveGraph(user); } });
Forwarding Object/Collections
Abstract implementations of existing types delegating all method calls to its delegate()
protected abstract Object delegate();
Decorator pattern without the burden ;)
Forwarding Collections
ForwardingCollection ForwardingConcurrentMap
ForwardingIterator ForwardingList
ForwardingListIterator ForwardingListMultimap
ForwardingMap ForwardingMapEntry ForwardingMultimap
ForwardingMultiset ForwardingObject ForwardingQueue
ForwardingSet ForwardingSetMultimap ForwardingSortedMap ForwardingSortedSet
ForwardingSortedSetMultimapForwardingTable
Static utilitiesIn classes with name ending with an s
‣ Lists‣ Maps‣ Multimaps‣ Multisets‣ Sets‣ SortedMaps‣ Tables‣ Iterators‣ Iterables‣ Collections2
Static factories methods
Map<String, Class<? extends Handler>> m = new HashMap<String, Class<? extends Handler>>();
Map<String, Class<? extends Handler>> m2 = Maps.newHashMap();
Guava provides these for JDK collections and for Guava collections (Multi*...)
With overloads to accept Iterables to copy elements from
Rather than typing
you type
+1
Maps as index
Maps.uniqueIndex()
Map<Integer, Employee> m = Maps.uniqueIndex(values, new Function<Employee, Integer>() { @Override public Integer apply(Employee input) { return input.getId(); }});
+1
Multimaps as index +1
Multimaps.index()
Multimap<Integer, Employee> m = Multimaps.index(values, new Function<Employee, Integer>() { @Override public Integer apply(Employee input) { return input.getYearsOfService(); }});
Map differences
So you want to compute the differences between two maps
Maps.difference( Map<? extends K,? extends V>, Map<? extends K,? extends V>)
+1
Guava has it too
Difference is an immutable snapshot of the state of the maps at the time this method is called
MapDifference API
Map<K,MapDifference.ValueDifference<V>> entriesDiffering()
Map<K,V> entriesInCommon() Map<K,V> entriesOnlyOnLeft() Map<K,V> entriesOnlyOnRight()
ValueDifference API
V leftValue() V rightValue()
Sets union/intersection/difference
difference(Set<E>, Set<?>)
symmetricDifference(Set<? extends E>, Set<? extends E>)
union(Set<? extends E>, Set<? extends E>)
intersection(Set<E>, Set<?>)
Returns Sets.SetView<E>
+1
Sets combinations
Set<Set<E>> powerSet(Set<E>)
Set<List<B>> cartesianProduct( List<? extends Set<? extends B>>)
while the power set of a set with size n is of size 2^n, its memory usage is only O(n)
while the cartesian product of sets of size m, n, p is a set of size m x n x p, its actual memory consumption is much smaller (m + n + p)
Immutable collections
JDK has Collections.unmodifiableFoo wrappers
‣Unmodifiable - you can't change it
‣Immutable - it can never change, no matter what
‣Immutability is tasty!‣See Effective Java Item 15 for some of the many reasons
http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf
Immutable collections
ImmutableListImmutableSetImmutableMap
ImmutableSortedMapImmutableSortedSetImmutableMultisetImmutableMultimap
ImmutableListMultimapImmutableSetMultimap
ImmutableBiMap
+1
http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf
Immutable collections
JDK wrappers still useful for unmodifiable views of changing data. But for most purposes, use Guava’s:
‣Brand-new, standalone implementations‣Immutability guaranteed!‣Very easy to use‣See following slides
‣Slightly faster‣Null hostile‣Use less memory‣Sometimes far less (ImmutableSet, factor of 2-3x)
http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf
Immutable collectionsFactory methods
ImmutableXXX.of()ImmutableXXX.of(E)ImmutableXXX.of(E, E)ImmutableXXX.of(E, E, E, E...)
ImmutableXXX.copyOf(Iterable)ImmutableXXX.copyOf(Iterator)
ImmutableMap.of(1, "one", 2, "two")ImmutableMap.copyOf(Map)
small maps only (up to 5 key/value pairs)
singletons
immutable empty XXX
Builder pattern otherwise
Constants Sets
public static final Set<Integer> LUCKY_NUMBERS; static { Set<Integer> set = new LinkedHashSet<Integer>(); set.add(4); set.add(8); set.add(15); set.add(16); set.add(23); set.add(42); LUCKY_NUMBERS = Collections.unmodifiableSet(set); }
http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
Constants Sets
public static final Set<Integer> LUCKY_NUMBERS = Collections .unmodifiableSet( new LinkedHashSet<Integer>( Arrays.asList(4, 8, 15, 16, 23, 42)));
A little nicer. But uses four different classes! Something's weird.
http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
Constants Sets
public static final ImmutableSet<Integer> LUCKY_NUMBERS = ImmutableSet.of(4, 8, 15, 16, 23, 42);
http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
Now we just say exactly what we mean. And get performance benefits as well!
We're using just one class (it implements Set)
of() method name inspired by java.util.EnumSet
Constants Maps
http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
public static final Map<String, Integer> ENGLISH_TO_INT;static { Map<String, Integer> map = new LinkedHashMap<String, Integer>(); map.put("four", 4); map.put("eight", 8); map.put("fifteen", 15); map.put("sixteen", 16); map.put("twenty-three", 23); map.put("forty-two", 42); ENGLISH_TO_INT = Collections.unmodifiableMap(map);}
Constants Maps
http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
public static final ImmutableMap<String, Integer> ENGLISH_TO_INT = ImmutableMap.<String,Integer>builder() .put("four", 4) .put("eight", 8) .put("fifteen", 15) .put("sixteen", 16) .put("twenty-three", 23) .put("forty-two", 42) .build();
Empowering the Builder Pattern!
TableCollection with columns and rows
No more Map<T1, Map<T2,T3>>
@Beta since r07
Table<R,C,V> composed of Table.Cell<R,C,V>
6 viewsSet<Table.Cell<R,C,V>> cellSet()
Map<R,V> column(C)Set<C> columnKeySet()
Map<C,Map<R,V>> columnMap()Map<C,V> row(R)
Set<R> rowKeySet()Map<R,Map<C,V>> rowMap()
Tables.transpose() (flips row and column keys)
2 impl.
HashBasedTableTreeBasedTable
Functionnalflavor
6
http://www.flickr.com/photos/leamarzloff/3085027173/
in com.google.common.base package
Function<F, T> to transform a collection
Predicate<T> to filter out a collection
public interface Function<F, T> {
T apply(F from);}
public interface Predicate<T> {boolean apply(T from);
}
in com.google.common.collect package
Iterables.filter()
Iterators.filter()
Collections2.filter()
Sets.filter()
http://www.flickr.com/photos/luis_is_rubbish_at_photography/5464233571/
4224 128
4224 7 12813
public static void demo(Collection<Integer> c) { Predicate<Integer> isEven = new Predicate<Integer>() { @Override public boolean apply(Integer input) { return (input.intValue() % 2 == 0); } }; Collection<Integer> fCol =
Collections2.filter(c, isEven); }
in com.google.common.collect package
Iterables.transform()
Iterators.transform()
Collections2.transform()
Lists.transform()
http://www.flickr.com/photos/brotherxii/2203037632/
ORANGEAPPLE KIWI PEARBANANA
OrangeApple Kiwi PearBanana
public void demo(Collection<String> c) { Function<String, String> toUpperCase = new Function<String, String>() { @Override public String apply(String input) { return input.toUpperCase(); } }; Collection<String> tCol = Collections2.transform(c, toUpperCase); }
Beware of
lazynesshttp://www.flickr.com/photos/torek/2467519466/
Copy!
Lists.newArrayList() Lists.newLinkedList() Sets.newHashSet() Sets.newLinkedHashSet() Sets.newTreeSet()
ImmutableList.copyOf() ImmutableSet.copyOf()
or make it immutable...
http://www.flickr.com/photos/visionnewspaper/314107094/
Predicates
Functions
composeforPredicate
andornotcompose
Compose and combine http://www.flickr.com/photos/jgscism/5484243543/
Compose and combine
Function<String, String> toUpper = new Function<String, String>() { @Override public String apply(String input) { return input.toUpperCase(); }};
Function<Integer, String> toHexString = new Function<Integer, String>() { @Override public String apply(Integer input) { return Integer.toHexString(input.intValue()); }};
Function<Integer, String> toUpperHexString = Functions.compose(toUpper, toHexString);
Compose and combine
Predicate<String> isEmpty = new Predicate<String>() { @Override public boolean apply(String input) { return input.length() == 0; // isEmpty() is Java6 only }};
Predicate<Object> isNull = new Predicate<Object>() { @Override public boolean apply(Object input) { return input == null; }};
Predicate<String> nullOfEmpty = Predicates.or(isNull, isEmpty);
Maps transform & filter
Maps.filterEntries()
Maps.filterKeys()
Maps.filterValues()
Maps.transformEntries()
Maps.transformValues()
Equivalence for Multimaps
Primitives
7
package that helps you work with the primitive types
common.primitives
int, long, double, float, char, byte, short, and boolean
If you need help doing a primitive task:
1. check the wrapper class (e.g. java.lang.Integer)2. check java.util.Arrays3. check com.google.common.primitives4. it might not exist!
http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
Guava doesn't do primitive-based collections; try fastutil, or trove4j, or...
common.primitives
Booleans, Bytes, Chars, Doubles, Floats, Ints, Longs and (wait for it) Shorts
Contains the classes
Each has the exact same structure (but has only the subset of operations that make sense for its type).
Many of the byte-related methods have alternate versions in the classes
SignedBytes and UnsignedBytes. (Bytes are peculiar...)
http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
Method Longs Ints Shorts Chars Doubles Bytes S.Bytes U.Bytes Booleans
hashCode x x x x x x x
compare x x x x x x x x
checkedCast x x x x x
saturadCast x x x x x
contains x x x x x x
indexOf x x x x x x x
lastIndexOf x x x x x x x
min x x x x x x
max x x x x x x
concat x x x x x x x
join x x x x x x x
toArray x x x x x x x
asList x x x x x x x
lexComparator x x x x x x x
toByteArray x x x x
fromByteArray x x x x
The big table
http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
IO & Network
8
http://www.flickr.com/photos/buzzingbye/222969493/
common.iopublic interface InputSupplier<T> { T getInput() throws IOException;} public interface OutputSupplier<T> { T getOutput() throws IOException;}
2 key interfaces
Typically: InputSupplier<InputStream>, OutputSupplier<Writer>, etc.
‣ byte stream means "InputStream or OutputStream"ByteStreams utilities class
‣ char stream means "Reader or Writer."CharStreams utilities class
Terminology
This lets all Guava’s utilities be useful for many kinds of I/O.
http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
‣byte[] toByteArray(InputStream) ‣byte[] toByteArray(InputSupplier) ‣void readFully(InputStream, byte[]) ‣void write(byte[], OutputSupplier) ‣long copy(InputStream, OutputStream) ‣long copy(InputSupplier, OutputSupplier) ‣long length(InputSupplier)‣boolean equal(InputSupplier, InputSupplier) ‣InputSupplier slice(InputSupplier, long, long) ‣InputSupplier join(InputSupplier...)
ByteStreams
CharStreams is similar, but deals in Reader, Writer, String and CharSequence (often requiring you to specify a Charset).
http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
Files The Files class works one level higher than ByteStreams and CharStreams
byte[] toByteArray(File) void write(byte[], File) void write(CharSequence, File, Charset) long copy(File, File) long copy(InputSupplier, File) long copy(File, OutputSupplier) long copy(File, Charset, Appendable) long move(File, File) boolean equal(File, File)
http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
More about Files
File createTempDir() void deleteDirectoryContents(File) void deleteRecursively(File) long getChecksum(File, Checksum) byte[] getDigest(File, MessageDigest) String readFirstLine(File, Charset) List<String> readLines(File, Charset) T readLines(File, Charset, LineProcessor<T>) String toString(File, Charset)
http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
Flushables and Closeables
Closeables.closeQuietly(Closeable closeable)Closeables.close(
Closeable closeable, boolean swallowIOException) throws IOException
Flushables.flushQuietly(Flushable flushable)Flushables.flush(
Flushable flushable, boolean swallowIOException) throws IOException
Very usefull in finally blocks (avoid nesting try/catch)
HostSpecifiersyntactically valid host specifier, suitable for use in a URI
InternetDomainName~RFC 1035, i18n DN
InetAddressesutility pertaining to Inet(4|6)Address instances
http://guava-libraries.googlecode.com/files/Guava_for_Netflix_.pdf
common.net
Work with literals of:‣URI‣URL‣@IP (v4/v6)
Never cause DNS services to be accessed
(JDK does...)
Concurrency
9http://www.flickr.com/photos/kh-67/3339157498/
Immutable* ConcurrentHashMultiset
Multimaps.synchronizedMultimap MapMaker
http://guava-libraries.googlecode.com/files/guava-concurrent-slides.pdf
Concurrency in Guava
http://guava-libraries.googlecode.com/files/guava-concurrent-slides.pdf
common.util.concurrent
It’s all about Future (as in java.util.concurrent)(never heard of it, go take a nap)
"A handle to an in-progress computation."
"A promise from a service to supply us with a result."
http://guava-libraries.googlecode.com/files/guava-concurrent-slides.pdf
Future
public interface Future<V> { //... V get(); //... }
JDK Future
Guava ListenableFuture
public interface ListenableFuture<V> extends Future<V> { void addListener(Runnable r, Executor e); }
Future with one new method: addListener
When the future is done (success, exception, cancellation), the listeners run
the killer app: "To serve as a foundation for higher-level abstractions"
See Futures
http://guava-libraries.googlecode.com/files/guava-concurrent-slides.pdf
ListenableFuture
When to use? Always.
(+) Most Futures methods require it. (+) It's easier than changing to ListenableFuture later. (+) Providers of utility methods won't need to provide Future and ListenableFuture variants of their methods.
(−) "ListenableFuture" is lengthier than "Future." (−) Classes like ExecutorService give you a plain Future by default.
http://guava-libraries.googlecode.com/files/guava-concurrent-slides.pdf
ListenableFuture
http://guava-libraries.googlecode.com/files/guava-concurrent-slides.pdf
Transform and chain
Function<QueryResult, List<Row>> rowsFunction = new Function<QueryResult, List<Row>>() { public List<Row> apply(QueryResult queryResult) { return queryResult.getRows(); }};
Future<QueryResult> queryFuture = ...; Future<List<Row>> rowsFuture = transform(queryFuture, rowsFunction);
http://guava-libraries.googlecode.com/files/guava-concurrent-slides.pdf
Transform and chain
Function<RowKey, ListenableFuture<QueryResult>> queryFunction = new Function<RowKey, ListenableFuture<QueryResult>>() { public ListenableFuture<QueryResult> apply(RowKey rowKey) { return dataService.read(rowKey); }};
ListenableFuture<RowKey> rowKeyFuture = indexService.lookUp(query);ListenableFuture<QueryResult> queryFuture = chain(rowKeyFuture, queryFunction);
http://guava-libraries.googlecode.com/files/guava-concurrent-slides.pdf
Futures
Got a Iterable<Future<V>>?
Decide what you want:
Future of List<V> List of Future<V>
Futures.allAsList()Futures.successfulAsList()
MoreExecutors.sameThreadExecutorfor quick tasks that can run inline
MoreExecutors.getExitingExecutorServicefor "half-daemon" threads
UncaughtExceptionHandlers.systemExitfor exiting after unexpected errors
ThreadFactoryBuildernew ThreadFactoryBuilder()
.setDaemon(true)
.setNameFormat("WebRequestHandler-%d")
.build();
http://guava-libraries.googlecode.com/files/guava-concurrent-slides.pdf
Executors
"An object with an operational state, plus asynchronous start() and stop() lifecycle methods
to transfer into and out of this state."
http://guava-libraries.googlecode.com/files/guava-concurrent-slides.pdf
Services
Example: web servers, RPC servers, monitoring initialization, ...
AbstractExecutionThreadService One thread automatically created for you at startup
AbstractIdleService Thread only needed for startup and shutdown (e.g., service that already has its own thread)
AbstractServiceFull control over threads creation
http://guava-libraries.googlecode.com/files/guava-concurrent-slides.pdf
Services
EMF for dummies
10http://www.flickr.com/photos/bendylan/259110679/
"Class diagram to Super Java Bean"
Java Framework and code generation facility
(My definition)
About those modeling things
‣It’s just about defining the entities/concepts/classes you will manipulate
‣You can define concepts in several ways‣Annotated Java classes‣XML Schema‣Ecore file‣UML Class diagram
‣You give the input to EMF, and it handles conversion and generation of the ULTIMATE POJO API
About those modeling things
‣Thin framework layer inserted into your POJO‣you can even hide it ;)
‣The layer is as thin as imaginable and provides high power-to-weight ratio‣opposite references‣adapters‣edit‣lazy loading‣serialization (REST)‣factory‣reflective calls / metadata generation
About those modeling things
What can you define in Ecore files?
‣Package‣Classes‣Attributes‣References
About those modeling things
‣PackagesLogical organization
‣ClassesClassical OO concepts
‣AttributesPrimitive type fields (with cardinality)
‣ReferencesClass type fields (with cardinality), opposite, containment
EObject?
The thin layer that changes it all
Object eGet(EStructuralFeature feature);void eSet(EStructuralFeature feature, Object newValue);boolean eIsSet(EStructuralFeature feature);void eUnset(EStructuralFeature feature);
EList<EObject> eContents();TreeIterator<EObject> eAllContents();EObject eContainer();
time to play
http://www.flickr.com/photos/squonk/1715142327/
http://www.flickr.com/photos/8728229@N07/4592234883/
EMFPath
11http://www.flickr.com/photos/eseartista/1604034788/
Path
Set of functions and predicates for EMF objects
Code generators for your own Ecore models
and few other utility classes
public interface Function<F, T> {
T apply(F from);
}public interface Predicate<T> {
boolean apply(T from);}
‣ parent (eContainer)
‣ ancestor‣ ancestorOrSelf‣ child (eContents)
‣ descendant (eAllContents)
‣ descendantOrSelf‣ following‣ followingSibling‣ preceding‣ precedingSibling
Lazy EObjects containment tree walking
EObject myObject;Collection<EObject> fs = followingSibling.of(myObject);
http
://w
ww
.flic
kr.c
om/p
hoto
s/m
usic
love
natu
re/1
4459
7827
2/
HavingIsKind/IsTypeIsAncestor/IsChild
Common predicates
public static Collection<EObject> demoHaving(Collection<EObject> c) {
return Collections2.filter(c, Having.feature(EcorePackage.Literals.ENAMED_ELEMENT__NAME,
StringPredicates.firstUpperCase) ); }
non-EMF functions & predicates
length : Function<String, Integer>toL1Case : Function<String, String>toLowerCase : Function<String, String>toU1Case : Function<String, String>toUpperCase : Function<String, String>trim : Function<String, String>replaceAll(Pattern, String)replaceAll(String, String)replaceFirst(Pattern, String)replaceFirst(String, String)substring(int)substring(int, int)
Strings
Predicates to test ordering:equalless thangreater thanless or equalgreater or equal
Comparable
Ecore API has been Guava-ified
‣ EObject.eResource() is wrapped as a Function in EObjectPath.eResource
‣ EObject.eIsProxy() is wrapped as a Predicate in EObjectPath.eIsProxy
‣ EClass.getESuperTypes() is wrapped as a Function in EClass.eSuperTypes
‣ EReference.isContainment() is wrapped as a Predicate in ERefrencePath.isContainment
Ecore has been Guava-ified through a generator
that is available for your own Ecore model
+
time to play
http://www.flickr.com/photos/squonk/1715142327/
http://www.flickr.com/photos/8728229@N07/4592234883/
Recap
12http://www.flickr.com/photos/loty/326761635/
1. Functionnal flavor of collection handling2. CharMatcher / Splitter / Joiner3. Immutable Collections4. Multimap / Multiset / Bimap5. MapMaker6. EMF is generating plain old POJO
What you should remember
about this presentation
1. Guava is cool, powerful and the definitive extension to JDK! 2. Never write your own POJO by hand for now, use EMF!3. Always generate EMFPath classes to handle EMF objects!
What you should REALLY remember
about this presentation
http://code.google.com/p/guava-libraries/http://code.google.com/p/guava-osgi/
http://eclipse.org/modeling/emf/http://code.google.com/a/eclipselabs.org/p/emfpath/
Q&A
http://www.flickr.com/photos/wwworks/4759535950/
Recommended