Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Cleaner code with Guava

Cleaner code with Guava

Cleaner code with Guava:
Guava features that can make your code cleaner

Alexandru Simonescu

February 28, 2016
Tweet

More Decks by Alexandru Simonescu

Other Decks in Programming

Transcript

  1. 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
  2. pros _increases readability _makes you analyze absent case _never forget

    if a value can be null _forces you to unwrap Optional
  3. where to use preconditions? validate arguments to methods checkArgument(boolean); IllegalArgumentException

    check for nulls checkNotNull(T); NullPointerException or <T> 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
  4. 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<Person> persons = PersonRepository.instance() .getByLimit(50); Ordering toString = Ordering.usingToString(); Collections.sort(persons, toString); Printer.print(persons);
  5. implement custom orderings Ordering<Person> orderBySuffix = new Ordering<Person>() { @Override

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

    int compare(Person p1, Person p2) { return p1.getSuffix().compareTo(p2.getSuffix()); } }; Ordering<Person> byNameLength = new Ordering<Person>() { @Override public int compare(Person p1, Person p2) { return Ints.compare(p1.getName().length(), p2.getName().length()); } }; List<Person> persons = PersonRepository.instance().getByLimit(50); Collections.sort(persons, byNameLength.compound(bySuffix)); Printer.print(persons);
  7. 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(); }
  8. joiner and splitter Joiner joiner = Joiner.on("; ").skipNulls(); return joiner.join("Harry",

    null, "Ron", "Hermione"); Splitter.on(',') .trimResults() .omitEmptyStrings() .split("foo,bar,, qux");
  9. 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
  10. 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 */
  11. 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
  12. 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
  13. _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<E> without ordering or Map<E, Integer> with elements and counts multiset count(Object): returns count associated with that element elementSet(): returns a Set<E> with the distinct elements of multiset entrySet(): returns Set<MultiSet. Entry<E>> which works as entry-set of Map<E>
  14. multimap _general way to associate keys to arbitrary values _alternative

    to Map<K, List<V>> or Map<K, Set<V>> _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
  15. bimap _better way to map values back to keys _values

    are unique, uses Set<E> _allows to view the inverse with BiMap<K, M>. inverse() _lots of implementations BiMap<String, Integer> userId = HashBiMap. create(); String userForId = userId.inverse().get(id); Map<String, Integer> nameToId = Maps. newHashMap(); Map<Integer, String> idToName = Maps. newHashMap(); nameToId.put("Bob", 42); idToName.put(42, "Bob");
  16. table Table<Vertex, Vertex, Double> 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
  17. class to instance map _used to map types to values

    of that type _eliminate need of casting with getInstance(Class<T>) and T putInstance(Class<T>, T) ClassToInstanceMap<Number> numbers = MutableClassToInstanceMap.create(); numbers.putInstance(Integer.class, Integer.valueOf(0)); numbers.putInstance(Double.class, Double.valueOf(1)); numbers.putInstance(Float.class, Float.valueOf(3));
  18. static constructors List<Type> list = Lists.newArrayList(); Map<KeyType, Type> map =

    Maps. newLinkedHashMap(); Set<Type> set = Sets.newHashSet(elements); List<String> elements = Lists.newArrayList("alpha", "beta", "gamma");
  19. 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
  20. functions and predicates Function<A, B> B apply(A input) Functions: _compose(Function<B,

    C>, Function<A, B>) Predicate<T> boolean apply(T input) Predicates: _isNull(), compose(Predicate, Function, and (Predicate), or(Predicate), not(Predicate), etc
  21. functional danger zone sometimes imperative version is more readable, concrete

    and efficient Multiset<Integer> lengths = HashMultiset.create( FluentIterable.from(strings) .filter(new Predicate<String>() { public boolean apply(String string) { return CharMatcher.JAVA_UPPER_CASE. matchesAllOf(string); } }) .transform(new Function<String, Integer>() { public Integer apply(String string) { return string.length(); } })); Multiset<Integer> lengths = HashMultiset. create(); for (String string : strings) { if (CharMatcher.JAVA_UPPER_CASE.matchesAllOf (string)) { lengths.add(string.length()); } }
  22. _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<String> listenableFuture = executorService.submit(new Callable<String>()…); listenableFuture.addListener(new Runnable() { @Override public void run() { runOnFutureTaskCompletion(); } }, executorService);
  23. future callback ExecutorService executorService = Executors. newCachedThreadPool(); ListeningExecutorService executor =

    MoreExecutors. listeningDecorator(executorService); ListenableFuture<String> future = executor.submit(new Callable<String>() { @Override public String call() throws Exception { Thread.sleep(1000); return "Task completed"; }}); Futures.addCallback(future, new FutureCallback<String>() { @Override public void onSuccess(String s) { System.out.println("Task succeed: " + s); } @Override public void onFailure(Throwable throwable) { System.out.println("Task failed"); }}, executor);
  24. what you should learn _new collections types: really opens your

    mind to more problem solving alternatives _optional _try concurrency
  25. cleaner code? _it all depends on you _use statically imported

    functions to shorter lines _lambdas make code even cleaner (retrolambda)