Slide 1

Slide 1 text

“Cleaner code” with Guava

Slide 2

Slide 2 text

Alexandru Simonescu http://alexsimo.com @alexsimonescu http://blog.alexsimo.com “Do what you love. Love what you do.” - Ray Bradbury [email protected]

Slide 3

Slide 3 text

We all love “nulls”

Slide 4

Slide 4 text

but what “null” really means?

Slide 5

Slide 5 text

failure? success? absence?

Slide 6

Slide 6 text

domain problems

Slide 7

Slide 7 text

screw nulls! we don’t need them!

Slide 8

Slide 8 text

but we use nulls.. why? _to represent some sort of absence _where there might have been a value _there is none _value can’t be found _something went wrong

Slide 9

Slide 9 text

1. what your null value means 2. find better alternative type enums constants builders

Slide 10

Slide 10 text

Optional _may contain non null value (reference is present) _may contain nothing (reference is absent)

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

pros _increases readability _makes you analyze absent case _never forget if a value can be null _forces you to unwrap Optional

Slide 14

Slide 14 text

Preconditions _better alternative to IllegalArgumentException: cleaner _shield your API/library

Slide 15

Slide 15 text

where to use preconditions? validate arguments to methods checkArgument(boolean); IllegalArgumentException check for nulls checkNotNull(T); NullPointerException or check valid elements in lists, string or array checkElementIndexI (int index, int size); IndexOutOfBoundsException check for valid positions in list, string or array (really usefull?) checkPositionIndex (int index, int size); IndexOutOfBoundsException

Slide 16

Slide 16 text

Ordering _better alternative to java’s Comparator _build complex comparators _default natural and lexicographical orderings

Slide 17

Slide 17 text

some tips _can convert Comparator into Ordering with Ordering.from(Comparator) _skip Comparator in favor of extending Ordering abstract class _complex ordering by chaining Orderings List persons = PersonRepository.instance() .getByLimit(50); Ordering toString = Ordering.usingToString(); Collections.sort(persons, toString); Printer.print(persons);

Slide 18

Slide 18 text

implement custom orderings Ordering orderBySuffix = new Ordering() { @Override public int compare(Person p1, Person p2) { return p1.getSuffix().compareTo(p2.getSuffix()); } }; List persons = PersonRepository.instance().getByLimit(50); Collections.sort(persons, orderBySuffix); Printer.print(persons);

Slide 19

Slide 19 text

chain orderings Ordering bySuffix = new Ordering() { @Override public int compare(Person p1, Person p2) { return p1.getSuffix().compareTo(p2.getSuffix()); } }; Ordering byNameLength = new Ordering() { @Override public int compare(Person p1, Person p2) { return Ints.compare(p1.getName().length(), p2.getName().length()); } }; List persons = PersonRepository.instance().getByLimit(50); Collections.sort(persons, byNameLength.compound(bySuffix)); Printer.print(persons);

Slide 20

Slide 20 text

useful ordering functions

Slide 21

Slide 21 text

Objects _commom methods when using objects _helpes you generate toString(), hashCode(), equals() and compareTo()

Slide 22

Slide 22 text

equals() Objects.equal("a", "a"); Objects.equal(null, "a"); Objects.equal("a", null); Objects.equal(null, null); hashCode() Objects.hashCode(field1, field2, ..., fieldn) toString() MoreObjects.toStringHelper(this) .add("x", 1) .toString(); compareTo() public int compareTo(Foo that) { return ComparisonChain.start() .compare(this.aString, that.aString) .compare(this.anInt, that.anInt) .compare(this.anEnum, that.anEnum, Ordering.natural().nullsLast()) .result(); }

Slide 23

Slide 23 text

Strings _we all use and love them _cleaner operations

Slide 24

Slide 24 text

joiner and splitter Joiner joiner = Joiner.on("; ").skipNulls(); return joiner.join("Harry", null, "Ron", "Hermione"); Splitter.on(',') .trimResults() .omitEmptyStrings() .split("foo,bar,, qux");

Slide 25

Slide 25 text

char matchers _predicates for chars: retain(extract), remove, trim, matches ANY NONE WHITESPACE BREAKING_WHITESPACE DIGIT JAVA_LETTER JAVA_DIGIT JAVA_DIGIT_OR_LETTER JAVA_ISO_CONTROL JAVA_LOWER_CASE JAVA_UPPER_CASE ASCII

Slide 26

Slide 26 text

how to use char matchers?

Slide 27

Slide 27 text

formats and char sets try { bytes = string.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { throw new AssertionError(e); } // better do this bytes = string.getBytes(Charsets.UTF_8); CaseFormat.UPPER_UNDERSCORE .to(CaseFormat.LOWER_CAMEL, "CONSTANT_NAME")); // returns "constantName" /* LOWER_CAMEL, LOWER_HYPHEN, LOWER_UNDERSCORE, UPPER_CAMEL, UPPER_UNDERSCORE */

Slide 28

Slide 28 text

Collections _immutable collections _new collections types not included in jdk

Slide 29

Slide 29 text

why immutables? _thread safe, so no race conditions _more memory efficient than mutable alternatives _safe for use by untrusted libraries _guava collections types doesn’t allow nulls

Slide 30

Slide 30 text

create immutable collections _all ImmutablesXXX (set/map) have following methods: _copyOf: (smart copy) avoids copying data when is safe to do _of _builder _asList: returns ImmutableList, constant-overhead view, rather than an explicit copy

Slide 31

Slide 31 text

where to use?

Slide 32

Slide 32 text

new collections in the hood _MultiSet _MultiMap _BiMap _ClassToInstanceMap _RangeSet

Slide 33

Slide 33 text

_generalization of the notion of set, in which members are allowed to appear more than once _the order is irrelevant: {x, y, y} == {y, x, y} _can be viewed as ArrayList without ordering or Map with elements and counts multiset count(Object): returns count associated with that element elementSet(): returns a Set with the distinct elements of multiset entrySet(): returns Set> which works as entry-set of Map

Slide 34

Slide 34 text

multimap _general way to associate keys to arbitrary values _alternative to Map> or Map> _useful implementations _conceptually can think about multimap as: a collection of mappings from single keys to single values: a -> 1 a -> 2 a -> 4 b -> 3 c -> 5 or as a mapping from unique keys to collections of values: a -> [1, 2, 4] b -> 3 c -> 5

Slide 35

Slide 35 text

bimap _better way to map values back to keys _values are unique, uses Set _allows to view the inverse with BiMap. inverse() _lots of implementations BiMap userId = HashBiMap. create(); String userForId = userId.inverse().get(id); Map nameToId = Maps. newHashMap(); Map idToName = Maps. newHashMap(); nameToId.put("Bob", 42); idToName.put(42, "Bob");

Slide 36

Slide 36 text

table Table weightedGraph = HashBasedTable.create(); weightedGraph.put(v1, v2, 4); weightedGraph.put(v1, v3, 20); weightedGraph.put(v2, v3, 5); weightedGraph.row(v1); weightedGraph.column(v3); _really a table like collection, surprise? _can access it as Map with rowMap() or as Set with rowKeySet() _implementations like HashBasedTable, TreeBasedTable, ImmutableBasedTable or ArrayTable

Slide 37

Slide 37 text

class to instance map _used to map types to values of that type _eliminate need of casting with getInstance(Class) and T putInstance(Class, T) ClassToInstanceMap numbers = MutableClassToInstanceMap.create(); numbers.putInstance(Integer.class, Integer.valueOf(0)); numbers.putInstance(Double.class, Double.valueOf(1)); numbers.putInstance(Float.class, Float.valueOf(3));

Slide 38

Slide 38 text

Collections Utils _easy usage of collections _alternatives to jdk java.util.Collections

Slide 39

Slide 39 text

interface Iterable interface Collection interface Set interface List interface Queue

Slide 40

Slide 40 text

static constructors List list = Lists.newArrayList(); Map map = Maps. newLinkedHashMap(); Set set = Sets.newHashSet(elements); List elements = Lists.newArrayList("alpha", "beta", "gamma");

Slide 41

Slide 41 text

iterables _concat(Iterable) _frequency(Iterable object) _partition(Iterable object) _getFirst(Iterable, T default) majority of operations are lazy

Slide 42

Slide 42 text

iterables - collection like _addAll(Collection addTo, Iterable toAdd) _removeAll(Iterable removeFrom, Collection toRemove) _contains(Iterable, Object) _get(Iterable, int) _retainAll(Iterable removeFrom, Collection toRetain) collections operations on iterables

Slide 43

Slide 43 text

sets theoretic operations _union(Set, Set) _intersection(Set, Set) _difference(Set, Set) _symmetricDifference(Set, Set) _cartesianProduct(List) _powerSet()

Slide 44

Slide 44 text

still not enough? create your own collections extensions Forwarding Decorators Peeking Iterator Abstract Iterator

Slide 45

Slide 45 text

Functional _kind of functional programming in java _still not scala or kotlin, but it’s something

Slide 46

Slide 46 text

functions and predicates Function B apply(A input) Functions: _compose(Function, Function) Predicate boolean apply(T input) Predicates: _isNull(), compose(Predicate, Function, and (Predicate), or(Predicate), not(Predicate), etc

Slide 47

Slide 47 text

functional danger zone sometimes imperative version is more readable, concrete and efficient Multiset lengths = HashMultiset.create( FluentIterable.from(strings) .filter(new Predicate() { public boolean apply(String string) { return CharMatcher.JAVA_UPPER_CASE. matchesAllOf(string); } }) .transform(new Function() { public Integer apply(String string) { return string.length(); } })); Multiset lengths = HashMultiset. create(); for (String string : strings) { if (CharMatcher.JAVA_UPPER_CASE.matchesAllOf (string)) { lengths.add(string.length()); } }

Slide 48

Slide 48 text

Concurrency _simpler way of using features in java _let’s you add finish callbacks

Slide 49

Slide 49 text

_allows us to register a callback to be executed when once task is completed _ussage: ListenableFuture.addCallback( Runnable, ExecutorService) listenable future ListneningExecutorService service = MoreExecutors.listeningDecorator (executorService); ListenableFuture listenableFuture = executorService.submit(new Callable()…); listenableFuture.addListener(new Runnable() { @Override public void run() { runOnFutureTaskCompletion(); } }, executorService);

Slide 50

Slide 50 text

future callback ExecutorService executorService = Executors. newCachedThreadPool(); ListeningExecutorService executor = MoreExecutors. listeningDecorator(executorService); ListenableFuture future = executor.submit(new Callable() { @Override public String call() throws Exception { Thread.sleep(1000); return "Task completed"; }}); Futures.addCallback(future, new FutureCallback() { @Override public void onSuccess(String s) { System.out.println("Task succeed: " + s); } @Override public void onFailure(Throwable throwable) { System.out.println("Task failed"); }}, executor);

Slide 51

Slide 51 text

what you should learn _new collections types: really opens your mind to more problem solving alternatives _optional _try concurrency

Slide 52

Slide 52 text

what to take care less possible to work well in android: _cache _eventbus

Slide 53

Slide 53 text

cleaner code? _it all depends on you _use statically imported functions to shorter lines _lambdas make code even cleaner (retrolambda)

Slide 54

Slide 54 text

want to learn more? _http://www.baeldung.com/category/guava/ _https://github.com/google/guava/wiki

Slide 55

Slide 55 text

sample project https://github.com/alexsimo/guava-demo

Slide 56

Slide 56 text

Thanks! questions? maybe later? @alexsimonescu or [email protected]