Google Guava & EMF @ GTUG Nantes
Upcoming SlideShare
Loading in...5

Google Guava & EMF @ GTUG Nantes






Total Views
Views on SlideShare
Embed Views



16 Embeds 1,474 1377 48 16 11 5 4 2 2 2 1 1 1 1 1 1 1


Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
Post Comment
Edit your comment

Google Guava & EMF @ GTUG Nantes Google Guava & EMF @ GTUG Nantes Presentation Transcript

  • GoogleGuava &EclipseModelingFramework2011/04/26 Mikaël Barbero
  • Introduction 1
  • About me‣ Modeling consultant‣ Research engineer‣ Trainer‣ Conference Speaker‣ Language guy ;) ‣ Eclipse committer ‣ Guava-OSGi packager ‣ EMFPath lead
  • Paris Nantes
  • Strategicmembers
  • AcceleoEMFCompareATLGMFOCLMylyn IntentEEF LeadingSTP
  • Ava ilable technologies
  • Guava Overview 2
  • About GuavaJava library used Superset of internally @ GoogleGoogle for years Collections
  • About Guava Apache License v2
  • About Guava s s ti on ti on c lle llec Co 5 Co a r03 a r08 gle v0. gle v1 uav uav G oo G oo G G2007 2008 2009 2010 2011 Frequent releases (quarterly base) Latest release (r09): April, 7th
  • Why using Guava?Simp lexity
  • Why using Guava?
  • Why using Guava?Mainstream?
  • Why using Guava?Helpingothers
  • Inside GuavaIO Networking Concurrency Primitive types Collections GWT compatibility is tested (see @GwtCompatible)
  • Comparison with Apache Commons Better BetterMore Modern Designed Supported Best practices Actively Java 5 developed and patterns (- commons 3.0)Respects JDK Google Orthogonality contracts (@Beta to test designs) depends on it (e.g., Google Guice)
  • B est rep.
  • Corest of the core 3
  • Objects classpublic 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(, && Objects.equal(this.nickname, that.nickname) && Objects.equal(this.favMovie, that.favMovie); } return false; } @Override public int hashCode() { return Objects.hashCode(name, nickname, favMovie); }} Example from
  • Objects classpublic 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); }} Example from
  • PreconditionsDefensive coding if (state != State.PLAYABLE) { throw new IllegalStateException( "Cant play movie; state is " + state); } Preconditions.checkState(state == State.PLAYABLE, "Cant play movie; state is %s", state); Example from
  • PreconditionsDefensive 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
  • Equivalences strategiespublic 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");
  • ThrowablesThrowables.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 @VisibleForTesting@GwtCompatible @GwtIncompatible
  • Strings 4
  • CharMatcher +1 StringUtil example: allAscii, collapse, collapseControlChars, collapseWhitespace, indexOfChars, lastIndexNotOf, numSharedChars, removeChars, removeCrLf, replaceChars, retainAllChars, strip, stripAndCollapse, stripNonDigits, ... Partial cross product of two notions: (a) whats 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).
  • Getting a CharMatcher CharMatcher.WHITESPACE (Unicode) CharMatcher.JAVA_DIGIT Predefined constants CharMatcher.ASCII (examples) CharMatcher.ANY Factory methods (examples) CharMatcher.isNot(_) CharMatcher.oneOf("aeiou").negate() CharMatcher.inRange(a, z).or(inRange(A, Z)) Subclass CharMatcher, implement matches(char c) Now check out all that you can do...
  • Using your CharMatcher ‣ 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 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 +1 JDK has splitter ‣ regular expression ‣ result as an array ‣ its way of handling empty pieces (which is very strange) Mini-puzzler ",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
  • Splitter e_s_jones/5060802981/ Splitter is String.split() on steroids
  • Splitter The default behavior is simplistic: //yields [" foo", " ", "bar", " quux", ""] Splitter.on(,).split(" foo, ,bar, quux,"); If you want extra features, ask for them! //yields ["foo", "bar", "quux"] Splitter.on(,) .trimResults() .omitEmptyStrings() .split(" foo, ,bar, quux,");
  • Ascii, CharsetsAscii list of bytes constants for each Char between 0x00 & 0x7FCharsets by G uaranteed to be supported ons al l Java platform implementati No more ‣Charsets.ISO_8859_1; try { bytes = string.getBytes("UTF-8"); ‣Charsets.US_ASCII; } catch (UnsupportedEncodingException e) { ‣Charsets.UTF_16; // how can this possibly happen? ‣Charsets.UTF_16BE; throw new AssertionError(e); } ‣Charsets.UTF_16LE; ‣Charsets.UTF_8;
  • StringsString str = Strings.emptyToNull(s);String str = Strings.nullToEmpty(s);boolean b = Strings.isNullOrEmpty(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".E xample, s);
  • Collections 5
  • Ordering { Co mparator<T> publ ic interface ); int compare(T, T abstract equals(Objec t); ean a bstract bool } Comparator is easy to implement, but a pain to use Push the Comparator<T> interface to the next level
  • Ordering 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) { = id; = name; this.yearsOfService = yearsOfService; } Simple public int getId() { return id; } public String getName() { return name; } data class 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(); } }
  • 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}]
  • Ordering Define your own Comparator 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()); } };
  • Ordering Create an Ordering from a Comparator Ordering<Employee> orderUsingYearsComparator = Ordering.from(yearsComparator); Use your ordering, e.g. to sort List<Employee> sortedCopy = orderUsingYearsComparator.sortedCopy(employeeList); System.out.println("sorted copy: " + sortedCopy); 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}]
  • Ordering toString() ordering Ordering<Object> toStringOrdering = Ordering.usingToString(); Natural ordering (Comparable<T>) Ordering<Employee> natural = Ordering.natural();
  • 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>) new TreeSet( Collection)Better than card duplicate s elements Do not dis Performed sort is stable
  • Ordering is configurable ‣ Ordering.reverse() ‣ Ordering.lexicographical() ‣ Ordering.nullsFirst() ‣ Ordering.nullsLast() ‣ Ordering.reverse()Lexicographical returns anOrdering on Iterable of T [] < [1] < [1, 1] < [1, 2] < [2]
  • ObjectArrays‣ concat(T, T[])‣ concat(T[], T)‣ concat(T[], T[], Class<T>)‣ newArray(Class<T>, int)‣ newArray(T[], int)
  • Multiset & MultimapHistorically, 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.
  • Multiset Ever done this? 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); } } distinct tags: tags.keySet() count for "java" tag: Usage tags.containsKey("java") ? tags.get("java") : 0; total count: // oh crap...
  • Multiset Would you rather do this? Multiset<String> tags = HashMultiset.create(); for (BlogPost post : getAllBlogPosts()) { tags.addAll(post.getTags()); } distinct tags: tags.elementSet(); Usage count for "java" tag: tags.count("java"); (hurrah) total count: tags.size();
  • Multiset API ‣What if you need to remove/decrement? ‣Dont accidentally go negative ‣Dont 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.) 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);
  • Multiset implementations +1 ImmutableMultiset HashMultiset LinkedHashMultiset TreeMultiset EnumMultiset ConcurrentHashMultiset
  • When to use Multimap? Ever done this? 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); }
  • When to use Multimap? Would you rather do this? Multimap<Salesperson, Sale> multimap = ArrayListMultimap.create(); public void makeSale(Salesperson salesPerson, Sale sale) { multimap.put(salesPerson, sale); } The code on the previous slide is ‣Verbose ‣Bug-prone ‣Limited in functionality ‣Using the wrong abstraction
  • More about Multimap A collection of key-value pairs (entries), like a Map, except that keys dont 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]}
  • 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 Hmm... sounds a lot like a plain old Map<K, Collection<V>>? But wait...
  • Multimap, before Now we want to find the biggest Sale. Without Multimap: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;}
  • Multimap, afterpublic Sale getBiggestSale() { return Collections.max(multimap.values(), SALE_CHARGE_COMPARATOR);} View collections are very powerful. Multimap has six: ‣get(), ‣keys(), ‣keySet(), ‣values(), ‣entries(), ‣asMap().
  • Multimap API Most 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()
  • Multimap implementations +1 ImmutableMultimap ImmutableListMultimap ImmutableSetMultimap ArrayListMultimap HashMultimap LinkedHashMultimap LinkedListMultimap TreeMultimap ListMultimap SetMultimap SortedSetMultimap
  • BiMap +1 aka unique-valued map values are unique, as well as its keys Has an inverse() view, which is another BiMap bimap.inverse().inverse() == bimap Stop creating two separate forward and backward Maps!
  • BiMap Implementations ImmutableBiMap HashBiMap EnumBiMap EnumHashBiMap
  • Constrained Collections/Mapspublic interface Constraint<E> { E checkElement(E element);} //... public Object checkElement(Object element) { if (element == null) { throw new NullPointerException(); } return element; } Constraints.n otNull() //...
  • Constrained Collections/MapsConstraints. 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>)
  • MapMaker +1A ConcurrentMap builder, providing any combination ofthese features: ‣Soft or weak keys ‣Soft or weak values ‣Timed expiration ‣On-demand computation of valuesFar more powerful, easy to use than WeakHashMapConcurrent on-demand computation is really hard
  • MapMakerConcurrentMap<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 ForwardingMultisetForwardingConcurrentMap ForwardingObject ForwardingIterator ForwardingQueue ForwardingList ForwardingSet ForwardingListIterator ForwardingSetMultimap ForwardingListMultimap ForwardingSortedMap ForwardingMap ForwardingSortedSet ForwardingMapEntry ForwardingSortedSetMultimap ForwardingMultimap ForwardingTable
  • Static utilitiesIn classes with name ending with an s ‣ Lists ‣ Maps ‣ Multimaps ‣ Multisets ‣ Sets ‣ SortedMaps ‣ Tables ‣ Iterators ‣ Iterables ‣ Collections2
  • Static factories methods +1Rather than typing Map<String, Class<? extends Handler>> m = new HashMap<String, Class<? extends Handler>>();you type 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
  • Maps as index +1Maps.uniqueIndex() Map<Integer, Employee> m = Maps.uniqueIndex(values, new Function<Employee, Integer>() { @Override public Integer apply(Employee input) { return input.getId(); } });
  • Multimaps as index +1Multimaps.index() Multimap<Integer, Employee> m = Multimaps.index(values, new Function<Employee, Integer>() { @Override public Integer apply(Employee input) { return input.getYearsOfService(); } });
  • Map differences +1 So you want to compute the differences between two maps Guava has it too Maps.difference( Map<? extends K,? extends V>, Map<? extends K,? extends V>)Difference is an immutable snapshot of the state of the maps at the time this method is called
  • MapDifference API Map<K,V> entriesInCommon() Map<K,V> entriesOnlyOnLeft() Map<K,V> entriesOnlyOnRight()Map<K,MapDifference.ValueDifference<V>> entriesDiffering() ValueDifference API V leftValue() V rightValue()
  • Sets union/intersection/difference +1difference(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>
  • Sets combinationsSet<Set<E>> powerSet(Set<E>) while the power set of a set with size n is of size 2^n, its memory usage is only O(n)Set<List<B>> cartesianProduct( List<? extends Set<? extends B>>) 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 cant change it ‣Immutable - it can never change, no matter what ‣Immutability is tasty! ‣See Effective Java Item 15 for some of the many reasons
  • Immutable collections +1 ImmutableList ImmutableSet ImmutableMap ImmutableSortedMap ImmutableSortedSet ImmutableMultiset ImmutableMultimap ImmutableListMultimap ImmutableSetMultimap ImmutableBiMap
  • 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)
  • Immutable collectionsFactory methods ImmutableXXX.of() immutable empty XXX ImmutableXXX.of(E) singletons ImmutableXXX.of(E, E) ImmutableXXX.of(E, E, E, E...) ImmutableXXX.copyOf(Iterable) ImmutableXXX.copyOf(Iterator) small maps only (up ImmutableMap.of(1, "one", 2, "two") to 5 key/value pairs) ImmutableMap.copyOf(Map)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); }
  • 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! Somethings weird.
  • Constants Sets public static final ImmutableSet<Integer> LUCKY_NUMBERS = ImmutableSet.of(4, 8, 15, 16, 23, 42); Now we just say exactly what we mean. And get performance benefits as well! Were using just one class (it implements Set) of() method name inspired by java.util.EnumSet
  • Constants Maps 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 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) Empowering the .put("twenty-three", 23) Builder Pattern! .put("forty-two", 42) .build();
  • Table @Beta since r07Collection with columns and rowsNo more Map<T1, Map<T2,T3>>Table<R,C,V> composed of Table.Cell<R,C,V>Tables.transpose() (flips row and column keys) 6 views 2 impl. Set<Table.Cell<R,C,V>> cellSet() Map<R,V> column(C) HashBasedTable Set<C> columnKeySet() TreeBasedTable Map<C,Map<R,V>> columnMap() Map<C,V> row(R) Set<R> rowKeySet() Map<R,Map<C,V>> rowMap()
  • Functionnal flavor 6
  • in package public interface Predicate<T> { Predicate<T> to filter boolean apply(T from); out a collection } {public interface Function<F, T> T apply(F from); Function<F, T> to} transform a collection
  • in package Iterables.filter() Iterators.filter() Collections2.filter() Sets.filter()
  • 24 42 13 7 128public 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); } 24 42 128
  • in package Iterables.transform() Iterators.transform()Collections2.transform() Lists.transform() /
  • Apple Orange Banana Kiwi Pearpublic 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); } APPLE ORANGE BANANA KIWI PEAR
  • Bewareoflazyness
  • Copy! Lists.newArrayList() Lists.newLinkedList() Sets.newHashSet() Sets.newLinkedHashSet() Sets.newTreeSet() or make it immutable... ImmutableList.copyOf() ImmutableSet.copyOf()
  • Compose and combine compose forPredicatePredicates and or not compose
  • 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 & filterMaps.filterEntries()Maps.filterKeys()Maps.filterValues()Maps.transformEntries()Maps.transformValues() Equivalence for Multimaps
  • Primitives 7
  • common.primitives package that helps you work with the primitive types 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.Arrays 3. check 4. it might not exist!
  • common.primitives Contains the classes Booleans, Each has the exact same structure Bytes, (but has only the subset of operations that make sense for its type). Chars, Doubles, Floats, Many of the byte-related methods Ints, have alternate versions in the classes Longs and (wait for it) SignedBytes and UnsignedBytes. (Bytes are peculiar...) Shorts Guava doesnt do primitive-based collections; try fastutil, or trove4j, or...
  • The big table 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
  • IO & Network 8
  • 2 key interfaces public interface InputSupplier<T> { T getInput() throws IOException; } Typically: public interface OutputSupplier<T> { InputSupplier<InputStream>, OutputSupplier<Writer>, etc. T getOutput() throws IOException; } This lets all Guava’s utilities be useful for many kinds of I/O. Terminology ‣ byte stream means "InputStream or OutputStream" ByteStreams utilities class ‣ char stream means "Reader or Writer." CharStreams utilities class
  • ByteStreams ‣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...) CharStreams is similar, but deals in Reader, Writer, String and CharSequence (often requiring you to specify a Charset).
  • 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)
  • 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)
  • Flushab les and Closeables Flushables.flushQuietly(Flushable flushable) Flushables.flush( Flushable flushable, boolean swallowIOException) throws IOException Closeables.closeQuietly(Closeable closeable) Closeables.close( Closeable closeable, boolean swallowIOException) throws IOException Very usefull in finally blocks (avoid nesting try/catch)
  • ‣URI Work with literals of: ‣URL ‣@IP (v4/v6) Never cause DNS services to be accessed (JDK does...) HostSpecifier syntactically valid host specifier, suitable for use in a URI InternetDomainName ~RFC 1035, i18n DN InetAddresses utility pertaining to Inet(4|6)Address instances
  • Concurrency 9
  • Concurrency in Guava Immutable* ConcurrentHashMultiset Multimaps.synchronizedMultimap MapMaker
  • comm on.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."
  • Future JDK Future public interface Future<V> { //... V get(); //... } Guava ListenableFuture public interface ListenableFuture<V> extends Future<V> { void addListener(Runnable r, Executor e); }
  • ListenableFuture 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
  • ListenableFuture When to use? Always. (+) Most Futures methods require it. (+) Its easier than changing to ListenableFuture later. (+) Providers of utility methods wont 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.
  • 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);
  • Transform and chain Function<RowKey, ListenableFuture<QueryResult>> queryFunction = new Function<RowKey, ListenableFuture<QueryResult>>() { public ListenableFuture<QueryResult> apply(RowKey rowKey) { return; } }; ListenableFuture<RowKey> rowKeyFuture = indexService.lookUp(query); ListenableFuture<QueryResult> queryFuture = chain(rowKeyFuture, queryFunction);
  • Futures Got a Iterable<Future<V>>? Decide what you want: Future of List<V> Futures.allAsList() List of Future<V> Futures.successfulAsList()
  • Executors MoreExecutors.sameThreadExecutor for quick tasks that can run inline MoreExecutors.getExitingExecutorService for "half-daemon" threads UncaughtExceptionHandlers.systemExit for exiting after unexpected errors ThreadFactoryBuilder new ThreadFactoryBuilder() .setDaemon(true) .setNameFormat("WebRequestHandler-%d") .build();
  • Services "An object with an operational state, plus asynchronous start() and stop() lifecycle methods to transfer into and out of this state." Example: web servers, RPC servers, monitoring initialization, ...
  • Services 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) AbstractService Full control over threads creation
  • EMF for dummies 10
  • Java Framework and code generation facility "Class diagram to Super Java Bean" (My definition)
  • Ab out those modeling things‣It’s just about defining the entities/concepts/classesyou 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 conversionand generation of the ULTIMATE POJO API
  • Ab out those modeling things‣Thin framework layer inserted into your POJO ‣you can even hide it ;)‣The layer is as thin as imaginable and provides highpower-to-weight ratio ‣opposite references ‣adapters ‣edit ‣lazy loading ‣serialization (REST) ‣factory ‣reflective calls / metadata generation
  • Ab out those modeling thingsWhat can you define in Ecore files? ‣Package ‣Classes ‣Attributes ‣References
  • Ab out those modeling things ‣Packages Logical organization ‣Classes Classical OO concepts ‣Attributes Primitive type fields (with cardinality) ‣References Class 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 883/ /photos/8728229@N07/4592234 /1715142327/
  • EMFPath 11
  • Path
  • { public interface Function<F, T> Set of functions and } T apply(F from); public interface Predicate<T> {predicates for EMF objects } boolean apply(T from); Code generators for your own Ecore modelsand few other utility classes
  • Lazy EObjects containment tree walking ‣ parent (eContainer) ‣ ancestor ‣ ancestorOrSelf ‣ child (eContents) ‣ descendant (eAllContents) 445978272/ ‣ descendantOrSelf ‣ following ‣ followingSibling ‣ preceding ‣ precedingSibling EObject myObject; Collection<EObject> fs = followingSibling.of(myObject);
  • Common predicates Having IsKind/IsType IsAncestor/IsChild 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 Stringslength : Function<String, Integer>toL1Case : Function<String, String> ComparabletoLowerCase : Function<String, String>toU1Case : Function<String, String> Predicates totoUpperCase : Function<String, String> test ordering:trim : Function<String, String> equal replaceAll(Pattern, String) less than replaceAll(String, String) greater than replaceFirst(Pattern, String) less or equal replaceFirst(String, String) greater or equal substring(int) substring(int, int)
  • Ecore API has been Guava-ified‣ EObject.eResource() is wrapped as a Function inEObjectPath.eResource‣ EObject.eIsProxy() is wrapped as a Predicate inEObjectPath.eIsProxy‣ EClass.getESuperTypes() is wrapped as aFunction in EClass.eSuperTypes‣ EReference.isContainment() is wrapped as aPredicate in ERefrencePath.isContainment
  • Ecore has been Guava-ified through a generator + that is available for your own Ecore model
  • time to play 883/ /photos/8728229@N07/4592234 /1715142327/
  • Recap 12
  • Wha t you should remember about this presentation1. Functionnal flavor of collection handling2. CharMatcher / Splitter / Joiner3. Immutable Collections4. Multimap / Multiset / Bimap5. MapMaker6. EMF is generating plain old POJO
  • What you should REALLY remember about this presentation1. Guava is cool, powerful and the definitiveextension to JDK!2. Never write your own POJO by hand fornow, use EMF!3. Always generate EMFPath classes tohandle EMF objects!