Google Guava

33
Google Guava by Yuriy Krutko Java Developer

Transcript of Google Guava

Page 1: Google Guava

Google Guava

by Yuriy KrutkoJava Developer

Page 2: Google Guava

Common Myths

Guava is a fruitGuavas (singular Guava, English pronunciation: /ˈgwɑː.və/[2]) are plants in the Myrtle family (Myrtaceae) genus Psidium (meaning "pomegranate" in Latin)

Guava misuses functional idioms

Guava is Google Collections

Page 3: Google Guava

What's inside

Preconditions

Ordering Throwables

Caches

Strings

PrimitivesRanges

I/OHashing

EventBus

Math

ReflectionObjects

CollectionsConcurrency

Page 4: Google Guava

Why Guava?

•Guava is a productivity multiplier

• I Could've Invented That

•"Know and use the libraries”

•Don't reinvent the wheel.

•Could not be included into Java API

Page 5: Google Guava

Guava Design Principles

• API is the best solution for use case.

• Obvious and intuitive outside. "Smart" inside.

• Encourage good code habits.

• Generic tools that can be composed.

• Emphasize maintainability.

Page 6: Google Guava

equals, hashCode, toString

Code it yourself

Generate using tools (e.g. Eclipse)

Use Guava Objects class

Page 7: Google Guava

Generated

private String firstName; private String secondName;

@Override public String toString() { return "PersonGenerated [firstName=" + firstName + ", secondName=" + secondName + "]"; }

@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((firstName == null) ? 0 : firstName.hashCode()); result = prime * result + ((secondName == null) ? 0 : secondName.hashCode()); return result; }

Page 8: Google Guava

Generate @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; PersonGenerated other = (PersonGenerated) obj; if (firstName == null) { if (other.firstName != null) return false; } else if (!firstName.equals(other.firstName)) return false; if (secondName == null) { if (other.secondName != null) return false; } else if (!secondName.equals(other.secondName)) return false; return true; }

Page 9: Google Guava

Objects private String firstName; private String secondName;

@Override public int hashCode() { return Objects.hashCode(firstName, secondName); }

@Override public boolean equals(Object obj) { if (obj instanceof PersonGuava) { PersonGuava other = (PersonGuava) obj; return Objects.equal(firstName, other.firstName) && Objects.equal(secondName, other.secondName); } return false; }

@Override public String toString() { return Objects.toStringHelper(this) .add("firstName", firstName) .add("secondName", secondName) .toString(); }

Page 10: Google Guava

Puzzler

Objects.hashCode(a) == a.hashCode() ?

Arrays.hashCode(new Object[] { a }) == a.hashCode() ?

public static int hashCode(Object a[]) { if (a == null) return 0;

int result = 1;

for (Object element : a) result = 31 * result

+ (element == null ? 0 : element.hashCode());

return result; }

Page 11: Google Guava

Compare while equalpublic class PairOfInts { private int first; private int second;

public static Comparator<PairOfInts> comparator() { return new Comparator<PairOfInts>() { @Override public int compare(PairOfInts p1, PairOfInts p2) { if (p1.first < p2.first) { return -1; } if (p1.first == p2.first) { if (p1.second < p2.second) { return -1; } if (p1.second == p2.second) { return 0; } } return 1; } }; } }

Page 12: Google Guava

Compare while equalpublic class PairOfInts { private int first; private int second;

public static Comparator<PairOfInts> comparator() { return new Comparator<PairOfInts>() { @Override public int compare(PairOfInts p1, PairOfInts p2) { if (p1.first < p2.first) { return -1; } if (p1.first == p2.first) { if (p1.second < p2.second) { return -1; } if (p1.second == p2.second) { return 0; } } return 1; } }; } }

public static Comparator<PairOfInts> comparatorInts() { return new Comparator<PairOfInts>() { @Override public int compare(PairOfInts p1, PairOfInts p2) { int res = Ints.compare(p1.first, p2.first); if (res == 0) { return Ints.compare(p1.second, p2.second); } return res; } }; }

Page 13: Google Guava

Compare while equalpublic class PairOfInts { private int first; private int second;

public static Comparator<PairOfInts> comparator() { return new Comparator<PairOfInts>() { @Override public int compare(PairOfInts p1, PairOfInts p2) { if (p1.first < p2.first) { return -1; } if (p1.first == p2.first) { if (p1.second < p2.second) { return -1; } if (p1.second == p2.second) { return 0; } } return 1; } }; } }

public static Comparator<PairOfInts> comparatorInts() { return new Comparator<PairOfInts>() { @Override public int compare(PairOfInts p1, PairOfInts p2) { int res = Ints.compare(p1.first, p2.first); if (res == 0) { return Ints.compare(p1.second, p2.second); } return res; } }; }

public static Ordering<PairOfInts> ordering() { return Ordering.from(new Comparator<PairOfInts>() { @Override public int compare(PairOfInts p1, PairOfInts p2) { return Ints.compare(p1.first, p2.first); } }).compound(new Comparator<PairOfInts>() { @Override public int compare(PairOfInts p1, PairOfInts p2) { return Ints.compare(p1.second, p2.second); } }); }

Page 14: Google Guava

Compare while equalpublic class PairOfInts { private int first; private int second;

public static Comparator<PairOfInts> comparator() { return new Comparator<PairOfInts>() { @Override public int compare(PairOfInts p1, PairOfInts p2) { if (p1.first < p2.first) { return -1; } if (p1.first == p2.first) { if (p1.second < p2.second) { return -1; } if (p1.second == p2.second) { return 0; } } return 1; } }; } }

public static Comparator<PairOfInts> comparatorInts() { return new Comparator<PairOfInts>() { @Override public int compare(PairOfInts p1, PairOfInts p2) { int res = Ints.compare(p1.first, p2.first); if (res == 0) { return Ints.compare(p1.second, p2.second); } return res; } }; }

public static Ordering<PairOfInts> ordering() { return Ordering.from(new Comparator<PairOfInts>() { @Override public int compare(PairOfInts p1, PairOfInts p2) { return Ints.compare(p1.first, p2.first); } }).compound(new Comparator<PairOfInts>() { @Override public int compare(PairOfInts p1, PairOfInts p2) { return Ints.compare(p1.second, p2.second); } }); }

public static Ordering<PairOfInts> orderingLexicographical() { return Ordering.<Comparable<?>> natural() .lexicographical().onResultOf( new Function<PairOfInts, Iterable<Comparable<?>>>() { @Override public Iterable<Comparable<?>> apply(PairOfInts pair) { return ImmutableList.<Comparable<?>> of(pair.first, pair.second); } }); }

Page 15: Google Guava

Compare while equalpublic class PairOfInts { private int first; private int second;

public static Comparator<PairOfInts> comparator() { return new Comparator<PairOfInts>() { @Override public int compare(PairOfInts p1, PairOfInts p2) { if (p1.first < p2.first) { return -1; } if (p1.first == p2.first) { if (p1.second < p2.second) { return -1; } if (p1.second == p2.second) { return 0; } } return 1; } }; } }

public static Comparator<PairOfInts> comparatorInts() { return new Comparator<PairOfInts>() { @Override public int compare(PairOfInts p1, PairOfInts p2) { int res = Ints.compare(p1.first, p2.first); if (res == 0) { return Ints.compare(p1.second, p2.second); } return res; } }; }

public static Ordering<PairOfInts> ordering() { return Ordering.from(new Comparator<PairOfInts>() { @Override public int compare(PairOfInts p1, PairOfInts p2) { return Ints.compare(p1.first, p2.first); } }).compound(new Comparator<PairOfInts>() { @Override public int compare(PairOfInts p1, PairOfInts p2) { return Ints.compare(p1.second, p2.second); } }); }

public static Ordering<PairOfInts> orderingLexicographical() { return Ordering.<Comparable<?>> natural() .lexicographical().onResultOf( new Function<PairOfInts, Iterable<Comparable<?>>>() { @Override public Iterable<Comparable<?>> apply(PairOfInts pair) { return ImmutableList.<Comparable<?>> of(pair.first, pair.second); } }); }

Page 16: Google Guava

Better Nullspublic class BetterNulls { public static final String DEFAULT = "default"; public String neverNullDefault(String value) { return Objects.firstNonNull(value, DEFAULT); } public String neverNullEmpty(String value) { return Strings.nullToEmpty(value); } public String getValueByKey(String key, Map<String, String> map) { return Functions.forMap(map, DEFAULT).apply(key); } public Optional<String> getValueByKeyOptional(String key, Map<String, String> map) { if (map.containsKey(key)) { return Optional.fromNullable(map.get(key)); } return null; }}

Page 17: Google Guava

Failfast and Join with Joy

public class PreconditionsJoiner { public String joinStrings(Iterable<String> strings) { Preconditions.checkNotNull(strings, "Strings should not be null"); return Joiner.on(", ").skipNulls().join(strings); }}

Page 18: Google Guava

Measure everything public void measureSomething() { Stopwatch stopwatch = new Stopwatch();

for (int i = 0; i < COUNT; i++) { stopwatch.start(); doSomething(); stopwatch.stop(); doUnimpotantThing(); stopwatch.start(); doOtherThing(); stopwatch.stop(); }

System.out.println("Average execution time " + stopwatch.elapsedTime(TimeUnit.NANOSECONDS) / COUNT + "ns"); }

Page 19: Google Guava

Fast and Immutable

public List<Integer> createList(int[] elements) { return ImmutableList.copyOf(Ints.asList(elements)); }

public Map<String, String> createMap() { return ImmutableMap.of("key1", "val1", "key2", "val2"); }

public Map<String, String> buildMap() { return ImmutableMap.<String, String> builder() .put("key1", "val1") .put("key2", "val2") .build(); }

Page 20: Google Guava

More collections public void biMap() { BiMap<Integer, String> biMap = HashBiMap.create(); BiMap<String, Integer> inverseBiMap = biMap.inverse(); } public void multimap() { Multimap<Integer, String> multiMap = ArrayListMultimap.create(); multiMap.put(10, "val1"); multiMap.put(10, "val2"); Collection<String> values = multiMap.get(10); }

Table<Vertex, Vertex, Double> weightedGraph = HashBasedTable.create(); weightedGraph.put(v1, v2, 4.0); weightedGraph.put(v1, v3, 20.0); weightedGraph.put(v2, v3, 5.0); Map<Vertex, Double> row = weightedGraph.row(v1); Map<Vertex, Double> column = weightedGraph.column(v3);

Page 21: Google Guava

Double checked lockingpublic class DCL { private static final Supplier<Object> supplier = Suppliers .memoize(new Supplier<Object>() { @Override public Object get() { return loadResource(); } });

private static Object loadResource() { return new Object(); } public static Object getResource() { return supplier.get(); }}

Page 22: Google Guava

Memoize and Expirepublic class DCLExp { private static final Supplier<Object> supplier = Suppliers .memoizeWithExpiration(new Supplier<Object>() { @Override public Object get() { return loadResource(); } }, 10, TimeUnit.MINUTES);

private static Object loadResource() { return new Object(); } public static Object getResource() { return supplier.get(); }}

Page 23: Google Guava

Cachepublic class CacheSample { private final LoadingCache<String, Object> cache = CacheBuilder.newBuilder() .maximumSize(1000) .initialCapacity(100) .concurrencyLevel(10) .expireAfterAccess(30, TimeUnit.SECONDS) .recordStats() .build(new CacheLoader<String, Object>() { @Override public Object load(String key) throws Exception { return loadResourceByKey(key); } });

private Object loadResourceByKey(String key) { return new Object(); } public Object getCachedValue(String key) { return cache.getUnchecked(key); } public CacheStats getStats() { return cache.stats(); }}

Page 24: Google Guava

Functional Idioms public static Multiset<Integer> one(Iterable<String> strings) { Function<String, Integer> lengthFunction = new Function<String, Integer>() { @Override public Integer apply(String string) { return string.length(); } }; Predicate<String> allCaps = new Predicate<String>() { @Override public boolean apply(String string) { return CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string); } }; return HashMultiset.create(Iterables.transform(

Iterables.filter(strings, allCaps), lengthFunction)); }

Page 25: Google Guava

Functional Idioms public static Multiset<Integer> two(Iterable<String> strings) { return HashMultiset.create( FluentIterable.from(strings) .filter(new Predicate<String>() { @Override public boolean apply(String string) { return CharMatcher.JAVA_UPPER_CASE

.matchesAllOf(string); } }) .transform(new Function<String, Integer>() { @Override public Integer apply(String string) { return string.length(); } })); }

Page 26: Google Guava

public static Multiset<Integer> one(Iterable<String> strings) { Function<String, Integer> lengthFunction = new Function<String, Integer>() { @Override public Integer apply(String string) { return string.length(); } }; Predicate<String> allCaps = new Predicate<String>() { @Override public boolean apply(String string) { return CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string); } }; return HashMultiset.create(Iterables.transform(

Iterables.filter(strings, allCaps), lengthFunction)); }

Functional Idioms public static Multiset<Integer> three(Iterable<String> strings) { Multiset<Integer> lengths = HashMultiset.create(); for (String string : strings) { if (CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string)) { lengths.add(string.length()); } } return lengths; }

Page 27: Google Guava

Catching a Buspublic class BaseEvent {}

public class SpecificEvent extends BaseEvent {}

public class OtherSpecificEvent extends BaseEvent {}

public interface EventListener { void handleSpecific(SpecificEvent event); void handleOtherSpecific(OtherSpecificEvent event);}

public class EventListenerAdapter implements EventListener { @Override public void handleSpecific(SpecificEvent event) { } @Override public void handleOtherSpecific(OtherSpecificEvent event) { }}

Page 28: Google Guava

Catching a Buspublic class EventDispatcher { private List<EventListener> listeners = new CopyOnWriteArrayList<EventListener>(); public void addListener(EventListener listener) { listeners.add(listener); } public void removeListener(EventListener listener) { listeners.add(listener); }

public void fireSpecific(SpecificEvent event) { for (EventListener listener : listeners) { listener.handleSpecific(event); } } public void fireOtherSpecific(OtherSpecificEvent event) { for (EventListener listener : listeners) { listener.handleOtherSpecific(event); } }}

Page 29: Google Guava

Event Bus

public class BaseEvent {}

public class SpecificEvent extends BaseEvent {}

public class OtherSpecificEvent extends BaseEvent {}

Page 30: Google Guava

Event Buspublic class EBExample { private static final EventBus eventBus = new EventBus();

public static void main(String[] args) { eventBus.register(new Object() { @Subscribe public void handle(SpecificEvent event) { System.out.println("SpecificEvent: " + event.getClass()); } });

eventBus.register(new Object() { @Subscribe @AllowConcurrentEvents public void handle(BaseEvent event) { System.out.println("BaseEvent: " + event.getClass()); } }); eventBus.post(new SpecificEvent()); }}

Page 31: Google Guava

Even more...

• IO

•Net

•Reflect

•Throwables

•Hashing

•Math

•CaseFormat

•Concurrency

Page 32: Google Guava

Apache Commons

• Just another library

•Commons > Guava (BCEL, Fvs, Email)

•Guava is more consistent

•Guava uses generics

•Guava \ Commons != {}

•Guava doesn't solve global tasks

•Don't shoot yourself in the foot with Guava

Page 33: Google Guava

Thank you !

● Yuriy Krutko ([email protected])

● Guava (http://code.google.com/p/guava-libraries/)