Guava & EMF

154
Google Guava 2011/04/26 Eclipse Modeling Framework & Mikaël Barbero

Transcript of Guava & EMF

Page 1: Guava & EMF

Google Guava

2011/04/26

EclipseModelingFramework

&

Mikaël Barbero

Page 2: Guava & EMF

Introduction

1http://www.flickr.com/photos/drspam/295023450/

Page 3: Guava & EMF

About me

‣ Modeling consultant‣ Research engineer‣ Trainer‣ Conference Speaker‣ Language guy ;)

‣ Eclipse committer‣ Guava-OSGi packager‣ EMFPath lead

Page 4: Guava & EMF

Nantes

Paris

Page 5: Guava & EMF

Strategic members

Page 6: Guava & EMF

AcceleoEMFCompareATLGMFOCLMylyn IntentEEFSTP

Leading

Page 7: Guava & EMF
Page 8: Guava & EMF
Page 9: Guava & EMF
Page 10: Guava & EMF
Page 11: Guava & EMF

Available technologies

Page 12: Guava & EMF

GuavaOverview

2http://www.flickr.com/photos/slowburn/2986303105/

Page 14: Guava & EMF
Page 15: Guava & EMF

Java library used internally @

Google for years

Superset of Google

Collections

About Guava

Page 16: Guava & EMF

About Guava

Apache License v2http://www.apache.org/licenses/LICENSE-2.0

Page 17: Guava & EMF

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

Page 18: Guava & EMF
Page 19: Guava & EMF
Page 20: Guava & EMF

Why using Guava?

Simplexity

http://www.flickr.com/photos/gio_vencato/4941064345/

Page 21: Guava & EMF

Why using Guava?

http://www.flickr.com/photos/reway2007/3300379295/

Page 22: Guava & EMF

Why using Guava?

http://www.flickr.com/photos/funtik/1175522045/

Mainstream?

Page 23: Guava & EMF

Why using Guava?

Helping others

http://www.flickr.com/photos/thearches/4381959041/

Page 24: Guava & EMF

IO Networking Concurrency

Primitive types Collections

Inside Guava

GWT compatibility is tested (see @GwtCompatible)

Page 25: Guava & EMF

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)

Page 26: Guava & EMF

Bestrep.

Page 27: Guava & EMF

Corest of the core

3http://www.flickr.com/photos/27384147@N02/5211738745/

Page 28: Guava & EMF

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

Page 29: Guava & EMF

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

Page 30: Guava & EMF

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

Page 31: Guava & EMF

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

Page 32: Guava & EMF

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);

Page 33: Guava & EMF

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");

Page 34: Guava & EMF

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);}

Page 35: Guava & EMF

@Annotation

@Beta

@GwtCompatible @GwtIncompatible

@VisibleForTesting

Page 36: Guava & EMF

Strings

4http://www.flickr.com/photos/gernot/2554175292/

Page 37: Guava & EMF

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

Page 38: Guava & EMF

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

Page 39: Guava & EMF

‣ 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

Page 40: Guava & EMF

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

Page 41: Guava & EMF

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

Page 43: Guava & EMF

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!

Page 44: Guava & EMF

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

Page 45: Guava & EMF

Strings

boolean b = Strings.isNullOrEmpty(s);

String str = Strings.emptyToNull(s);

String str = Strings.nullToEmpty(s);

Page 46: Guava & EMF

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

Page 47: Guava & EMF

Collections

5http://www.flickr.com/photos/tochis/1169807846/

Page 48: Guava & EMF

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);

}

Page 49: Guava & EMF

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

Page 50: Guava & EMF

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

Page 51: Guava & EMF

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

Page 52: Guava & EMF

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

Page 53: Guava & EMF

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

Page 54: Guava & EMF

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)

Page 55: Guava & EMF

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

Page 56: Guava & EMF

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

Page 57: Guava & EMF

ObjectArrays

‣ concat(T, T[])

‣ concat(T[], T)

‣ concat(T[], T[], Class<T>)

‣ newArray(Class<T>, int)

‣ newArray(T[], int)

Page 58: Guava & EMF

Multiset & Multimap

Historically, multisets (aka bags) and multimaps emulated atop maps

Multimap = Map<K, List<V>>

Multiset = Map<K, Integer>

Page 59: Guava & EMF

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

Page 60: Guava & EMF

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

Page 61: Guava & EMF

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)

Page 62: Guava & EMF

‣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.

Page 63: Guava & EMF

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

Page 64: Guava & EMF

Multiset implementations

ImmutableMultisetHashMultisetLinkedHashMultisetTreeMultisetEnumMultisetConcurrentHashMultiset

http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf

+1

Page 65: Guava & EMF

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?

Page 66: Guava & EMF

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?

Page 67: Guava & EMF

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

Page 68: Guava & EMF

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...

Page 69: Guava & EMF

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

Page 70: Guava & EMF

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.

Page 71: Guava & EMF

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

Page 72: Guava & EMF

Multimap implementations

ImmutableMultimapImmutableListMultimapImmutableSetMultimap

ArrayListMultimapHashMultimap

LinkedHashMultimapLinkedListMultimap

TreeMultimap

http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf

ListMultimapSetMultimap

SortedSetMultimap

+1

Page 73: Guava & EMF

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

Page 74: Guava & EMF

BiMap Implementations

ImmutableBiMap HashBiMap EnumBiMapEnumHashBiMap

http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf

Page 75: Guava & EMF

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()

Page 76: Guava & EMF

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.

Page 77: Guava & EMF

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

Page 78: Guava & EMF

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); } });

Page 79: Guava & EMF

Forwarding Object/Collections

Abstract implementations of existing types delegating all method calls to its delegate()

protected abstract Object delegate();

Decorator pattern without the burden ;)

Page 80: Guava & EMF

Forwarding Collections

ForwardingCollection ForwardingConcurrentMap

ForwardingIterator ForwardingList

ForwardingListIterator ForwardingListMultimap

ForwardingMap ForwardingMapEntry ForwardingMultimap

ForwardingMultiset ForwardingObject ForwardingQueue

ForwardingSet ForwardingSetMultimap ForwardingSortedMap ForwardingSortedSet

ForwardingSortedSetMultimapForwardingTable

Page 81: Guava & EMF

Static utilitiesIn classes with name ending with an s

‣ Lists‣ Maps‣ Multimaps‣ Multisets‣ Sets‣ SortedMaps‣ Tables‣ Iterators‣ Iterables‣ Collections2

Page 82: Guava & EMF

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

Page 83: Guava & EMF

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

Page 84: Guava & EMF

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(); }});

Page 85: Guava & EMF

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

Page 86: Guava & EMF

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()

Page 87: Guava & EMF

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

Page 88: Guava & EMF

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)

Page 89: Guava & EMF

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

Page 90: Guava & EMF

Immutable collections

ImmutableListImmutableSetImmutableMap

ImmutableSortedMapImmutableSortedSetImmutableMultisetImmutableMultimap

ImmutableListMultimapImmutableSetMultimap

ImmutableBiMap

+1

http://google-collections.googlecode.com/files/google-collections-svgtug-2008-08-06.pdf

Page 91: Guava & EMF

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

Page 92: Guava & EMF

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

Page 93: Guava & EMF

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

Page 94: Guava & EMF

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

Page 95: Guava & EMF

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

Page 96: Guava & EMF

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);}

Page 97: Guava & EMF

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!

Page 98: Guava & EMF

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

Page 99: Guava & EMF

Functionnalflavor

6

http://www.flickr.com/photos/leamarzloff/3085027173/

Page 100: Guava & EMF

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);

}

Page 101: Guava & EMF

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/

Page 102: Guava & EMF

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); }

Page 103: Guava & EMF

in com.google.common.collect package

Iterables.transform()

Iterators.transform()

Collections2.transform()

Lists.transform()

http://www.flickr.com/photos/brotherxii/2203037632/

Page 104: Guava & EMF

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); }

Page 105: Guava & EMF

Beware of

lazynesshttp://www.flickr.com/photos/torek/2467519466/

Page 106: Guava & EMF

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/

Page 107: Guava & EMF

Predicates

Functions

composeforPredicate

andornotcompose

Compose and combine http://www.flickr.com/photos/jgscism/5484243543/

Page 108: Guava & EMF

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);

Page 109: Guava & EMF

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);

Page 110: Guava & EMF

Maps transform & filter

Maps.filterEntries()

Maps.filterKeys()

Maps.filterValues()

Maps.transformEntries()

Maps.transformValues()

Equivalence for Multimaps

Page 111: Guava & EMF

Primitives

7

Page 112: Guava & EMF

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

Page 113: Guava & EMF

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

Page 114: Guava & EMF

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

Page 115: Guava & EMF

IO & Network

8

http://www.flickr.com/photos/buzzingbye/222969493/

Page 116: Guava & EMF

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

Page 117: Guava & EMF

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).

Page 118: Guava & EMF

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)

Page 119: Guava & EMF

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)

Page 120: Guava & EMF

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)

Page 121: Guava & EMF

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...)

Page 122: Guava & EMF

Concurrency

9http://www.flickr.com/photos/kh-67/3339157498/

Page 123: Guava & EMF

Immutable* ConcurrentHashMultiset

Multimaps.synchronizedMultimap MapMaker

http://guava-libraries.googlecode.com/files/guava-concurrent-slides.pdf

Concurrency in Guava

Page 124: Guava & EMF

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."

Page 125: Guava & EMF

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); }

Page 126: Guava & EMF

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

Page 127: Guava & EMF

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

Page 128: Guava & EMF

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);

Page 129: Guava & EMF

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);

Page 130: Guava & EMF

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()

Page 131: Guava & EMF

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

Page 132: Guava & EMF

"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, ...

Page 133: Guava & EMF

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

Page 134: Guava & EMF

EMF for dummies

10http://www.flickr.com/photos/bendylan/259110679/

Page 135: Guava & EMF

"Class diagram to Super Java Bean"

Java Framework and code generation facility

(My definition)

Page 136: Guava & EMF

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

Page 137: Guava & EMF

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

Page 138: Guava & EMF

About those modeling things

What can you define in Ecore files?

‣Package‣Classes‣Attributes‣References

Page 139: Guava & EMF

About those modeling things

‣PackagesLogical organization

‣ClassesClassical OO concepts

‣AttributesPrimitive type fields (with cardinality)

‣ReferencesClass type fields (with cardinality), opposite, containment

Page 140: Guava & EMF

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

Page 142: Guava & EMF

EMFPath

11http://www.flickr.com/photos/eseartista/1604034788/

Page 143: Guava & EMF

Path

Page 144: Guava & EMF

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);}

Page 145: Guava & EMF

‣ 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/

Page 146: Guava & EMF

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) ); }

Page 147: Guava & EMF

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

Page 148: Guava & EMF

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

Page 149: Guava & EMF

Ecore has been Guava-ified through a generator

that is available for your own Ecore model

+

Page 151: Guava & EMF

Recap

12http://www.flickr.com/photos/loty/326761635/

Page 152: Guava & EMF

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

Page 153: Guava & EMF

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/