Google Guava & EMF @ GTUG Nantes

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/

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://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();

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

+

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/