Google Guava - Core libraries for Java & Android

  • 5,993 views
Uploaded on

Talk at GDG DevFest Barcelona 2013. …

Talk at GDG DevFest Barcelona 2013.

The Guava project contains several of Google's core libraries that we rely on in our Java-based projects: collections, caching, primitives support, concurrency libraries, common annotations, string processing, I/O, and so forth.

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
5,993
On Slideshare
0
From Embeds
0
Number of Embeds
10

Actions

Shares
Downloads
140
Comments
0
Likes
28

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Google Guava Core libraries for Java & Android @jordi9 11 / oct / 2013
  • 2. ...shameless self-promotion bro!
  • 3. Write less code
  • 4. Write cleaner code
  • 5. Write more readable code
  • 6. The “wheel”
  • 7. com.google.guava:guava:15.0
  • 8. Basics
  • 9. Basics Avoid using null
  • 10. Basics: Avoid using null “Null sucks” Doug Lea - JCP, OpenJDK
  • 11. Basics: Avoid using null “I call it my billion-dollar mistake” Sir C.A.R. Hoare - Inventor of null
  • 12. Basics: Avoid using null @Google 95% of collections weren’t supposed to have null values.
  • 13. map = {Foo: bar, null, Baz: qux} Basics: Avoid using null
  • 14. map = {Foo: bar, null, Baz: qux} map.get(“Foo”); Basics: Avoid using null
  • 15. map = {Foo: bar, null, Baz: qux} map.get(“Foo”); // returns Foo Basics: Avoid using null
  • 16. map = {Foo: bar, null, Baz: qux} map.get(“Foo”); map.get(“quux”); Basics: Avoid using null
  • 17. map = {Foo: bar, null, Baz: qux} map.get(“Foo”); map.get(“quux”); // returns null Basics: Avoid using null
  • 18. map = {Foo: bar, null, Baz: qux} map.get(“Foo”); map.get(“quux”); map.get(null); Basics: Avoid using null
  • 19. map = {Foo: bar, null, Baz: qux} map.get(“Foo”); map.get(“quux”); map.get(null); // returns null Basics: Avoid using null
  • 20. map = {Foo: bar, null, Baz: qux} map.get(“Foo”); map.get(“quux”); // returns null map.get(null); // returns null Basics: Avoid using null
  • 21. map = {Foo: bar, null, Baz: qux} map.get(“Foo”); map.get(“quux”); // returns null map.get(null); // returns null // Null to indicate absence // vs null value Basics: Avoid using null
  • 22. Optional<T> Basics: Avoid using null
  • 23. Optional<T> Optional<String> foo = Optional.of(“foo”) Basics: Avoid using null
  • 24. Optional<T> Optional<String> foo = Optional.of(“foo”) foo.isPresent(); // returns true Basics: Avoid using null
  • 25. Optional<T> Optional<String> foo = Optional.of(“foo”) foo.isPresent(); foo.get(); // returns “foo” Basics: Avoid using null
  • 26. Optional.of(foo); // not nullable Goodies! RTFM, I mean javadoc
  • 27. Optional.of(foo); Optional.absent(); Goodies! javadoc
  • 28. Optional.of(foo); Optional.absent(); Optional.fromNullable(legacyCode); Goodies! javadoc
  • 29. Optional.of(foo); Optional.absent(); Optional.fromNullable(legacyCode); foo.get(); // may return “foo” Goodies! javadoc
  • 30. Optional.of(foo); Optional.absent(); Optional.fromNullable(legacyCode); foo.get(); foo.or(“bar”); // return “bar” if foo is absent Goodies! javadoc
  • 31. Optional.of(foo); Optional.absent(); Optional.fromNullable(legacyCode); foo.get(); foo.or(“bar”); foo.orNull(); // Deal with code that need nulls, duh Goodies! javadoc
  • 32. Optional<T> is IDIOT-PROOF-NESS Bottom line
  • 33. Basics Preconditions
  • 34. if (seats <= 0) { throw new IllegalArgumentException(“Seats must be positive, but was ” + seats); } Basics: Preconditions
  • 35. if (seats <= 0) { throw new IllegalArgumentException(“Seats must be positive, but was ” + seats); } checkArgument(seats > 0, “Seats must be positive, but was %s”, seats); Basics: Preconditions
  • 36. // Always use static import import static com.google.common.base.Preconditions.checkArgument; checkArgument(seats > 0, “Seats must be positive, but was %s”, seats); Basics: Preconditions
  • 37. import static com.google.common.base.Preconditions.checkArgument; // Check what you expect to be true checkArgument(seats > 0, “Seats must be positive, but was %s”, seats); Basics: Preconditions
  • 38. import static com.google.common.base.Preconditions.checkArgument; // “%s” specifier is recognized as a placeholder in // these messages (the only one) checkArgument(seats > 0, “Seats must be positive, but was %s”, seats); Basics: Preconditions
  • 39. void execute(Job job) { // serious business } Basics: Preconditions
  • 40. void execute(Job job) { checkNotNull(job, “Job can’t be null”); // serious business } // checkNotNull() throws NullPointerException Basics: Preconditions
  • 41. void execute(Job job) { checkNotNull(job, “Job can’t be null”); checkArgument(!job.started(), “Job already started”); // serious business } // checkArgument() throws IllegalArgumentException // checkNotNull() throws NullPointerException Basics: Preconditions
  • 42. void execute(Job job) { checkNotNull(job, “Job can’t be null”); checkArgument(!job.started(), “Job already started”); // serious business checkState(seatsAvailabe <= totalSeats, “You’ve sold more seats than available! This should never happen. %s/%s”, seatsAvailable, totalSeats); } // checkState() throws IllegalStateException // checkArgument() throws IllegalArgumentException // checkNotNull() throws NullPointerException Basics: Preconditions
  • 43. this.foo = checkNotNull(foo); // inline assig Goodies! javadoc
  • 44. this.foo = checkNotNull(foo); // list, string or array checks checkElementIndex(index, size); checkPositionIndex(index, size); checkPositionIndexes(start, end, size); Goodies! javadoc
  • 45. Preconditions will save your ass Bottom line
  • 46. Basics Objects
  • 47. @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj == null || obj.getClass() != this.getClass()) { return false; } Person guest = (Person) obj; return id == guest.id && (firstName == guest.firstName || (firstName != null && firstName.equals(guest.getFirstName()))) && (lastName == guest.lastName || (lastName != null && lastName.equals(guest.getLastName()))); } Basics: Objects
  • 48. @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj == null || obj.getClass() != this.getClass()) { return false; } Person guest = (Person) obj; return id == guest.id && (firstName == guest.firstName || (firstName != null && firstName.equals(guest.getFirstName()))) && (lastName == guest.lastName || (lastName != null && lastName.equals(guest.getLastName()))); } Basics: Objects F
  • 49. @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj == null || obj.getClass() != this.getClass()) { return false; } Person guest = (Person) obj; return id == guest.id && (firstName == guest.firstName || (firstName != null && firstName.equals(guest.getFirstName()))) && (lastName == guest.lastName || (lastName != null && lastName.equals(guest.getLastName()))); } Basics: Objects FM
  • 50. @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj == null || obj.getClass() != this.getClass()) { return false; } Person guest = (Person) obj; return id == guest.id && (firstName == guest.firstName || (firstName != null && firstName.equals(guest.getFirstName()))) && (lastName == guest.lastName || (lastName != null && lastName.equals(guest.getLastName()))); } Basics: Objects FML
  • 51. @Override public boolean equals(Object obj) { if (obj instanceof Person) { Person that = (Person) obj; return Objects.equal(firstName, that.firstName) && Objects.equal(lastName, that.lastName); } else { return false; } } Basics: Objects
  • 52. @Override public boolean equals(Object obj) { if (obj instanceof Person) { Person that = (Person) obj; return Objects.equal(firstName, that.firstName) // null safe! && Objects.equal(lastName, that.lastName); // null safe x2! } else { return false; } } Basics: Objects
  • 53. @Override public boolean equals(Object obj) { if (obj instanceof Person) { Person that = (Person) obj; return Objects.equal(firstName, that.firstName) && Objects.equal(lastName, that.lastName); } else { return false; } } // JDK 1.7 introduced equivalent Objects.equals() method. Basics: Objects
  • 54. @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((firstName == null) ? 0 : firstName.hashCode()); result = prime * result + id; result = prime * result + ((lastName == null) ? 0 : lastName.hashCode()); return result; } Basics: Objects
  • 55. @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((firstName == null) ? 0 : firstName.hashCode()); result = prime * result + id; result = prime * result + ((lastName == null) ? 0 : lastName.hashCode()); return result; } // oh, grumpy cat! Basics: Objects
  • 56. @Override public int hashCode() { return Objects.hashCode(firstName, lastName); } Basics: Objects
  • 57. @Override public int hashCode() { // sensible, order-sensitive hash return Objects.hashCode(firstName, lastName); } Basics: Objects
  • 58. @Override public int hashCode() { return Objects.hashCode(firstName, lastName); } // JDK 1.7 introduced equivalent Objects.hash() method. Basics: Objects
  • 59. @Override public String toString() { } Basics: Objects
  • 60. @Override public String toString() { } Basics: Objects
  • 61. @Override public String toString() { return Objects.toStringHelper(this) .add("firstName", firstName) .add("lastName", lastName) .add("catName", catName) .toString(); } Basics: Objects
  • 62. @Override public String toString() { return Objects.toStringHelper(this) .add("firstName", firstName) .add("lastName", lastName) .add("catName", catName) .toString(); } // returns Person{firstName=Solid, lastName=Snake, catName=null} Basics: Objects
  • 63. @Override public String toString() { return Objects.toStringHelper(this) .add("firstName", firstName) .add("lastName", lastName) .add("catName", catName) .omitNullValues() .toString(); } Basics: Objects
  • 64. @Override public String toString() { return Objects.toStringHelper(this) .add("firstName", firstName) .add("lastName", lastName) .add("catName", catName) .omitNullValues() .toString(); } // returns Person{firstName=Solid, lastName=Snake} Basics: Objects
  • 65. IntelliJ IDEA support for ToStringHelper() Generate toString() > Template Objects.ToStringHelper (Guava) Goodies! javadoc
  • 66. So common stuff should ring a bell Bottom line
  • 67. Basics Ordering
  • 68. Comparator<Person> byDescAgeName = new Comparator<Person>() { public int compare(Person p1, Person p2) { int result = p2.getAge() - p1.getAge(); // ugh! return (result == 0) ? p1.compareTo(p2) : result; } }; // Ok, it’s not that bad -- But it’s pretty hard to get Basics: Ordering
  • 69. Comparator<Person> byDescAgeName = new Comparator<Person>() { public int compare(Person p1, Person p2) { int result = p2.getAge() - p1.getAge(); // ugh! return (result == 0) ? p1.compareTo(p2) : result; } }; // Ok, it’s not that bad -- But it’s pretty hard to get // We’re lucky ints and Person are Comparable, otherwise you’ll // have to implement it Basics: Ordering
  • 70. Comparator<Person> byDescAgeName = new Comparator<Person>() { public int compare(Person p1, Person p2) { return ComparisonChain.start() .compare(p2.getAge(), p1.getAge()) .compare(p1, p2) .result(); } }; Basics: Ordering
  • 71. Comparator<Person> byDescAgeName = new Comparator<Person>() { public int compare(Person p1, Person p2) { return ComparisonChain.start() .compare(p2.getAge(), p1.getAge()) .compare(p1, p2) .result(); } }; // Short-circuits: If one comparison is not equals, stop and return Basics: Ordering
  • 72. Comparator<Person> byDescAgeName = Ordering.natural() .reverse() .onResultOf(new Function<Person, Integer>() { public Integer apply(Person person) { return person.getAge(); }}) .compound(Ordering.natural()); } }; Basics: Ordering
  • 73. Comparator<Person> byDescAgeName = Ordering.natural() .reverse() .onResultOf(new Function<Person, Integer>() { public Integer apply(Person person) { return person.getAge(); }}) .compound(Ordering.natural()); } }; // Read backwards Basics: Ordering
  • 74. Ordering is an “enriched” Comparator. It’s fuuuuuuuun! Goodies! javadoc
  • 75. Ordering is an “enriched” Comparator. It’s fluent. Goodies! javadoc
  • 76. Ordering is an “enriched” Comparator. It’s fluent. // Subclass Ordering and implement compare(T,T) Ordering<Throwable> ORDER_BY_CLASS_NAME = (left, right) -> { return Ordering.usingToString() .compare(left.getClass(), right.getClass()); }; Goodies! javadoc
  • 77. Ordering is an “enriched” Comparator. It’s fluent. // Subclass Ordering and implement compare(T,T) Ordering<Throwable> ORDER_BY_CLASS_NAME = (left, right) -> { return Ordering.usingToString() .compare(left.getClass(), right.getClass()); }; // Or create one Ordering.from(comparator); Ordering.natural(); Goodies! javadoc
  • 78. Ordering is an “enriched” Comparator. It’s fluent. // Subclass Ordering and implement compare(T,T) Ordering<Throwable> ORDER_BY_CLASS_NAME = (left, right) -> { return Ordering.usingToString() .compare(left.getClass(), right.getClass()); }; // Or create one Ordering.from(comparator); Ordering.natural(); // And chain! ORDER_BY_CLASS_NAME.nullsFirst().reverse().compound(comparator); Goodies! javadoc
  • 79. There’s a better way than Comparator Bottom line
  • 80. Basics Throwables
  • 81. void oneLineOfCode() { DatagramPacket packet = new DatagramPacket(data, length); } Basics: Throwables
  • 82. void oneLineOfCode() { DatagramPacket packet = new DatagramPacket(data, length); } // Compile error, throws IOException Basics: Throwables
  • 83. void oneLineOfCode() throws IOException { DatagramPacket packet = new DatagramPacket(data, length); } void someLayer() { oneLineOfCode(); } Basics: Throwables
  • 84. void oneLineOfCode() throws IOException { DatagramPacket packet = new DatagramPacket(data, length); } void someLayer() { oneLineOfCode(); } // Compile error, throws IOException Basics: Throwables
  • 85. void oneLineOfCode() throws IOException { DatagramPacket packet = new DatagramPacket(data, length); } void someLayer() throws IOException { oneLineOfCode(); } void someCoolAbstraction() { someLayer(); } Basics: Throwables
  • 86. void oneLineOfCode() throws IOException { DatagramPacket packet = new DatagramPacket(data, length); } void someLayer() throws IOException { oneLineOfCode(); } void someCoolAbstraction() { someLayer(); } // Compile error, AGAIN Basics: Throwables
  • 87. void oneLineOfCode() throws IOException { DatagramPacket packet = new DatagramPacket(data, length); } void someLayer() throws IOException { oneLineOfCode(); } void someCoolAbstraction() throws IOException { someLayer(); } Basics: Throwables
  • 88. void oneLineOfCode() throws IOException { DatagramPacket packet = new DatagramPacket(data, address); } void someLayer() throws IOException { oneLineOfCode(); } void someCoolAbstraction() throws IOException { someLayer(); } // c’mon... Basics: Throwables
  • 89. void oneLineOfCode() { // Take 2 DatagramPacket packet = new DatagramPacket(data, length); } Basics: Throwables
  • 90. void oneLineOfCode() { try { DatagramPacket packet = new DatagramPacket(data, length); } catch (IOException e) { } } Basics: Throwables
  • 91. void oneLineOfCode() { try { DatagramPacket packet = new DatagramPacket(data, length); } catch (IOException e) { // Really? Swallow? Sure? At least explain why! } } Basics: Throwables
  • 92. void oneLineOfCode() { try { DatagramPacket packet = new DatagramPacket(data, length); } catch (IOException e) { SendMeAnEmail.error(); } } Basics: Throwables
  • 93. void oneLineOfCode() { try { DatagramPacket packet = new DatagramPacket(data, length); } catch (IOException e) { SendMeAnEmail.error(); Oh.theLogger().fatal(“WHY Y U FATAL NOW?”); } } Basics: Throwables
  • 94. void oneLineOfCode() { try { DatagramPacket packet = new DatagramPacket(data, length); } catch (IOException e) { SendMeAnEmail.error(); Oh.theLogger().fatal(“WHY Y U FATAL NOW?”); // repeat for every catch block } } Basics: Throwables
  • 95. void oneLineOfCode() { try { DatagramPacket packet = new DatagramPacket(data, length); } catch (IOException e) { SendMeAnEmail.error(); Oh.theLogger().fatal(“WHY Y U FATAL NOW?”); // repeat for every catch block // AGAIN AND AGAIN } } Basics: Throwables
  • 96. void oneLineOfCode() { try { DatagramPacket packet = new DatagramPacket(data, address); } catch (IOException e) { SendMeAnEmail.error(); Oh.theLogger().fatal(“WHY Y U FATAL NOW?”); // repeat for every catch block // AGAIN AND AGAIN } } Basics: Throwables
  • 97. void oneLineOfCode() { // Take 3 DatagramPacket packet = new DatagramPacket(data, length); } Basics: Throwables
  • 98. void oneLineOfCode() { try { DatagramPacket packet = new DatagramPacket(data, length); } catch (IOException e) { handle(e); } } // We know what to do with this Exception, like recover Basics: Throwables
  • 99. void oneLineOfCode() { try { DatagramPacket packet = new DatagramPacket(data, length); } catch (IOException e) { throw new MyException(e); } } // Translate the Exception to another one more suitable Basics: Throwables
  • 100. void oneLineOfCode() { try { DatagramPacket packet = new DatagramPacket(data, length); } catch (IOException e) { throw Throwables.propagate(e); } } // Propagates the throwable as-is if it is a RuntimeException or // an Error, or wraps it in a RuntimeException and throws it // otherwise. Basics: Throwables
  • 101. // more forms propagateIfInstanceOf(throwable,exceptionClass); Goodies… or gotcha’s! javadoc
  • 102. // more forms propagateIfInstanceOf(throwable,exceptionClass); propagateIfPossible(throwable); // Only if RuntimeException or Error Goodies… or gotcha’s! javadoc
  • 103. // more forms propagateIfInstanceOf(throwable,exceptionClass); propagateIfPossible(throwable); propagateIfPossible(throwable, exceptionClass); Goodies… or gotcha’s! javadoc
  • 104. // more forms propagateIfInstanceOf(throwable,exceptionClass); propagateIfPossible(throwable); propagateIfPossible(throwable, exceptionClass); General practice: Convert checked exceptions to unchecked exceptions Goodies… or gotcha’s! javadoc
  • 105. // more forms propagateIfInstanceOf(throwable,exceptionClass); propagateIfPossible(throwable); propagateIfPossible(throwable, exceptionClass); General practice: Convert checked exceptions to unchecked exceptions Checked exceptions... are a bad idea? Goodies… or gotcha’s! javadoc
  • 106. // more forms propagateIfInstanceOf(throwable,exceptionClass); propagateIfPossible(throwable); propagateIfPossible(throwable, exceptionClass); General practice: Convert checked exceptions to unchecked exceptions Checked exceptions... are a bad idea? Don’t use propagate() to ignore IOExceptions and so on Goodies… or gotcha’s! javadoc
  • 107. Think your fraking Exceptions Bottom line
  • 108. Strings
  • 109. Strings Splitter
  • 110. We have String.split bro! Strings: Splitter
  • 111. We have String.split bro! “,f,,o, o,”.split(“,”) returns: Strings: Splitter
  • 112. We have String.split bro! “,f,,o, o,”.split(“,”) returns: a. [“”, “f”, “”, “o”, “ o”,””] Strings: Splitter
  • 113. We have String.split bro! “,f,,o, o,”.split(“,”) returns: a. [“”, “f”, “”, “o”, “ o”,””] b. [null, “f”, null, “o” ,”o”, null] Strings: Splitter
  • 114. We have String.split bro! “,f,,o, o,”.split(“,”) returns: a. [“”, “f”, “”, “o”, “ o”,””] b. [null, “f”, null, “o” ,”o”, null] c. [“f”, null, “o”, “o”] Strings: Splitter
  • 115. We have String.split bro! “,f,,o, o,”.split(“,”) returns: a. [“”, “f”, “”, “o”, “ o”,””] b. [null, “f”, null, “o” ,”o”, null] c. [“f”, null, “o”, “o”] d. [“f”, ”o”, ”o”] Strings: Splitter
  • 116. We have String.split bro! “,f,,o, o,”.split(“,”) returns: a. [“”, “f”, “”, “o”, “ o”,””] b. [null, “f”, null, “o” ,”o”, null] c. [“f”, null, “o”, “o”] d. [“f”, ”o”, ”o”] e. None of above Strings: Splitter
  • 117. We have String.split bro! “,f,,o, o,”.split(“,”) returns: a. [“”, “f”, “”, “o”, “ o”,””] b. [null, “f”, null, “o” ,”o”, null] c. [“f”, null, “o”, “o”] d. [“f”, ”o”, ”o”] e. None of above Strings: Splitter
  • 118. We have String.split bro! “,f,,o, o,”.split(“,”) returns: a. [“”, “f”, “”, “o”, “ o”,””] b. [null, “f”, null, “o” ,”o”, null] c. [“f”, null, “o”, “o”] d. [“f”, ”o”, ”o”] e. None of above Strings: Splitter
  • 119. We have String.split bro! “,f,,o, o,”.split(“,”) returns: a. [“”, “f”, “”, “o”, “ o”,””] b. [null, “f”, null, “o” ,”o”, null] c. [“f”, null, “o”, “o”] d. [“f”, ”o”, ”o”] e. None of above Returns: [“”, “f”, “”, “o”, “ o”] Strings: Splitter
  • 120. We have String.split bro! “,f,,o, o,”.split(“,”) returns: a. [“”, “f”, “”, “o”, “ o”,””] b. [null, “f”, null, “o” ,”o”, null] c. [“f”, null, “o”, “o”] d. [“f”, ”o”, ”o”] e. None of above Returns: [“”, “f”, “”, “o”, “ o”] Only trailing empty strings are skipped. Strings: Splitter
  • 121. “,f,,o, o,”.split(“,”) we probably want [“f”,”o”,”o”] Strings: Splitter
  • 122. “,f,,o, o,”.split(“,”) we probably want [“f”,”o”,”o”] Splitter.on(‘,’) .split(“,f,,o, o,”); Strings: Splitter
  • 123. “,f,,o, o,”.split(“,”) we probably want [“f”,”o”,”o”] Splitter.on(‘,’) .split(“,f,,o, o,”); // returns [“”,”f”,””,”o”,” o”,””] // Doesn’t discard trailing separators! Strings: Splitter
  • 124. “,f,,o, o,”.split(“,”) we probably want [“f”,”o”,”o”] Splitter.on(‘,’) .omitEmptyStrings() .split(“,f,,o, o,”); Strings: Splitter
  • 125. “,f,,o, o,”.split(“,”) we probably want [“f”,”o”,”o”] Splitter.on(‘,’) .omitEmptyStrings() .split(“,f,,o, o,”); // returns [”f”,”o”,” o”] // Empty space is respected Strings: Splitter
  • 126. “,f,,o, o,”.split(“,”) we probably want [“f”,”o”,”o”] Splitter.on(‘,’) .omitEmptyStrings() .trimResults() .split(“,f,,o, o,”); Strings: Splitter
  • 127. “,f,,o, o,”.split(“,”) we probably want [“f”,”o”,”o”] Splitter.on(‘,’) .omitEmptyStrings() .trimResults() .split(“,f,,o, o,”); // returns [”f”,”o”,”o”] -- yay! Strings: Splitter
  • 128. “,f,,o, o,”.split(“,”) we probably want [“f”,”o”,”o”] static final Splitter COMMA = Splitter.on(‘,’) .omitEmptyStrings() .trimResults() .split(“,f,,o, o,”); // Best practice: declare Splitters as static final Strings: Splitter javadoc
  • 129. Strings Joiner
  • 130. [“Jack, “Chloe”, “Tony”, null, “Nina”, “Logan”] Strings: Joiner
  • 131. [“Jack, “Chloe”, “Tony”, null, “Nina”, “Logan”] Joiner.on(“, “) .join(twentyFour); Strings: Joiner
  • 132. [“Jack, “Chloe”, “Tony”, null, “Nina”, “Logan”] Joiner.on(“, “) .join(twentyFour); // throws NullPointerException! Strings: Joiner
  • 133. [“Jack, “Chloe”, “Tony”, null, “Nina”, “Logan”] Joiner.on(“, “) .join(twentyFour); // throws NullPointerException! // null-hostile operations everywhere, good thing ;) Strings: Joiner
  • 134. [“Jack, “Chloe”, “Tony”, null, “Nina”, “Logan”] Joiner.on(“, “) .skipNulls(); .join(twentyFour); // returns “Jack, Chloe, Tony, Nina, Logan” Strings: Joiner
  • 135. [“Jack, “Chloe”, “Tony”, null, “Nina”, “Logan”] Joiner.on(“, “) .useForNull(“Bill”); .join(twentyFour); // returns “Jack, Chloe, Tony, Bill, Nina, Logan” Strings: Joiner javadoc
  • 136. Always think how to avoid null-idioty Bottom line
  • 137. Strings CharMatcher
  • 138. Your StringUtils replacement Strings: CharMatcher
  • 139. Your StringUtils replacement CharMatcher.JAVA_ISO_CONTROL.removeFrom(string); // remove control chars Strings: CharMatcher
  • 140. Your StringUtils replacement CharMatcher.JAVA_ISO_CONTROL.removeFrom(string); CharMatcher.DIGIT.retainFrom(“jordi9”); // returns 9 Strings: CharMatcher
  • 141. Your StringUtils replacement CharMatcher.JAVA_ISO_CONTROL.removeFrom(string); CharMatcher.DIGIT.retainFrom(“jordi9”); CharMatcher.DIGIT.removeFrom(“jordi9”); // returns jordi Strings: CharMatcher
  • 142. Your StringUtils replacement CharMatcher.JAVA_ISO_CONTROL.removeFrom(string); CharMatcher.DIGIT.retainFrom(“jordi9”); CharMatcher.DIGIT.removeFrom(“jordi9”); CharMatcher.DIGIT.or(CharMatcher.JAVA_UPPER_CASE).retainFrom(“Jordi9”); // returns J9 Strings: CharMatcher
  • 143. // More matchers CharMatcher.ANY; CharMatcher.BREAKING_WHITESPACE; CharMatcher.WHITESPACE; CharMatcher.INVISIBLE; CharMatcher.DIGIT; // Unicode CharMatcher.JAVA_DIGIT; // Java’s definition CharMatcher.is(char); CharMatcher.isNot(char); Goodies! javadoc
  • 144. // More matchers CharMatcher.ANY; CharMatcher.BREAKING_WHITESPACE; CharMatcher.WHITESPACE; CharMatcher.INVISIBLE; CharMatcher.DIGIT; // Unicode CharMatcher.JAVA_DIGIT; // Java’s definition CharMatcher.is(char); CharMatcher.isNot(char); // And operations .replaceFrom(charSequence, replacement); .collapseFrom(charSequence, replacement); .trimFrom(charSequence, replacement); Goodies! javadoc
  • 145. Strings Escapers
  • 146. HtmlEscapers.htmlEscaper().escape("Foo > bar"); // returns Foo &gt; bar Escapers
  • 147. HtmlEscapers.htmlEscaper().escape("Foo > bar"); XmlEscapers.xmlAttributeEscaper().escape("foo "bar""); // returns foo &quot;bar&quot; Escapers
  • 148. HtmlEscapers.htmlEscaper().escape("Foo > bar"); XmlEscapers.xmlAttributeEscaper().escape("foo "bar""); XmlEscapers.xmlContentEscaper().escape("foo "bar""); // returns foo “bar” Escapers
  • 149. HtmlEscapers.htmlEscaper().escape("Foo > bar"); XmlEscapers.xmlAttributeEscaper().escape("foo "bar""); XmlEscapers.xmlContentEscaper().escape("foo "bar""); Escaper myEscaper = Escapers.builder() // custom Escaper .addEscape(‘’’, “‘’”) .addEscape(‘&’, “&”) .build(); Escapers javadoc
  • 150. Collections
  • 151. Collections: Functional Idiom
  • 152. Collections: Functional Idiom
  • 153. Collections: Functional Idiom
  • 154. Function<String, Integer> lengthFunction = new Function<String, Integer>() { public Integer apply(String string) { return string.length(); } }; Predicate<String> allCaps = new Predicate<String>() { public boolean apply(String string) { return CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string); } }; Multiset<Integer> lengths = HashMultiset.create( Iterables.transform(Iterables.filter(strings, allCaps), lengthFunction)); Collections: Functional Idiom
  • 155. Function<String, Integer> lengthFunction = new Function<String, Integer>() { public Integer apply(String string) { return string.length(); } }; Predicate<String> allCaps = new Predicate<String>() { public boolean apply(String string) { return CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string); } }; Multiset<Integer> lengths = HashMultiset.create( Iterables.transform(Iterables.filter(strings, allCaps), lengthFunction)); Collections: Functional Idiom
  • 156. Multiset<Integer> lengths = HashMultiset.create(); for (String string : strings) { if (CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string)) { lengths.add(string.length()); } } Collections: Functional Idiom
  • 157. Multiset<Integer> lengths = HashMultiset.create(); for (String string : strings) { if (CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string)) { lengths.add(string.length()); } } // Use Imperative, you’ve already survived! Collections: Functional Idiom
  • 158. Multiset<Integer> lengths = HashMultiset.create(); for (String string : strings) { if (CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string)) { lengths.add(string.length()); } } // Use Imperative, you’ve already survived! // Wait for Java 8! Collections: Functional Idiom explain
  • 159. Immutable = Thread-safe Collections: Immutable types
  • 160. Immutable = Thread-safe static final ImmutableSet<String> FOO_NAMES = ImmutableSet.of(“foo”, “bar”, “baz”); Collections: Immutable types
  • 161. Immutable = Thread-safe static final ImmutableSet<String> FOO_NAMES = ImmutableSet.of(“foo”, “bar”, “baz”); // ImmutableList, ImmutableMap... Collections: Immutable types
  • 162. Immutable = Thread-safe static final ImmutableSet<String> FOO_NAMES = ImmutableSet.of(“foo”, “bar”, “baz”); ImmutableList<String> defensiveCopy = ImmutableList.copyOf(someList); Collections: Immutable types
  • 163. Immutable = Thread-safe static final ImmutableSet<String> FOO_NAMES = ImmutableSet.of(“foo”, “bar”, “baz”); ImmutableList<String> defensiveCopy = ImmutableList.copyOf(someList); // Prefer Immutable collections over JDK Collections.unmodifiableXX // for efficiency and consistency Collections: Immutable types explain
  • 164. A bag Collections: Multiset<E>
  • 165. A bag Just like a Set<E> with repeated values Collections: Multiset<E>
  • 166. A bag Just like a Set<E> with repeated values You’ve done this with ArrayList<E> or Map<E, Integer> Collections: Multiset<E>
  • 167. A bag Just like a Set<E> with repeated values You’ve done this with ArrayList<E> or Map<E, Integer> Multiset<Person> ppl = HashMultiset.create(); Collections: Multiset<E>
  • 168. A bag Just like a Set<E> with repeated values You’ve done this with ArrayList<E> or Map<E, Integer> Multiset<Person> ppl = HashMultiset.create(); ppl.add(jack); ppl.add(charles); ppl.add(jack); Collections: Multiset<E>
  • 169. A bag Just like a Set<E> with repeated values You’ve done this with ArrayList<E> or Map<E, Integer> Multiset<Person> ppl = HashMultiset.create(); ppl.add(jack); ppl.add(charles); ppl.add(jack); // prints [jack x 2, charles x 1] Collections: Multiset<E>
  • 170. A bag Just like a Set<E> with repeated values You’ve done this with ArrayList<E> or Map<E, Integer> Multiset<Person> ppl = HashMultiset.create(); ppl.add(jack); ppl.add(charles); ppl.add(jack); ppl.count(jack); Collections: Multiset<E>
  • 171. A bag Just like a Set<E> with repeated values You’ve done this with ArrayList<E> or Map<E, Integer> Multiset<Person> ppl = HashMultiset.create(); ppl.add(jack); ppl.add(charles); ppl.add(jack); ppl.count(jack); // returns 2 Collections: Multiset<E>
  • 172. A bag Just like a Set<E> with repeated values You’ve done this with ArrayList<E> or Map<E, Integer> Multiset<Person> ppl = HashMultiset.create(); ppl.add(jack); ppl.add(charles); ppl.add(jack); ppl.count(jack); // Goodies: elementSet(), entrySet(), setCount(E, int)... Collections: Multiset<E> explain
  • 173. A Map<K, V> with multiple values Collections: Multimap<K, V>
  • 174. A Map<K, V> with multiple values You’ve done this with Map<K, List<V>> Collections: Multimap<K, V>
  • 175. A Map<K, V> with multiple values You’ve done this with Map<K, List<V>> Multimap<Person, Ticket> ticketsByPerson = ArrayListMultimap.create(); Collections: Multimap<K, V>
  • 176. A Map<K, V> with multiple values You’ve done this with Map<K, List<V>> Multimap<Person, Ticket> ticketsByPerson = ArrayListMultimap.create(); ticketsByPerson.put(jack, ctu); ticketsByPerson.put(jack, division); Collections: Multimap<K, V>
  • 177. A Map<K, V> with multiple values You’ve done this with Map<K, List<V>> Multimap<Person, Ticket> ticketsByPerson = ArrayListMultimap.create(); ticketsByPerson.put(jack, ctu); ticketsByPerson.put(jack, division); ticketsByPerson.get(jack); // returns a view of the associated values, a List. // With SetMultimap returns a Set. Collections: Multimap<K, V>
  • 178. A Map<K, V> with multiple values You’ve done this with Map<K, List<V>> Multimap<Person, Ticket> ticketsByPerson = ArrayListMultimap.create(); ticketsByPerson.put(jack, ctu); ticketsByPerson.put(jack, division); ticketsByPerson.get(jack); // asMap(), entries(), values()... Collections: Multimap<K, V> explain
  • 179. // Bi-directional map, keys and values are unique BiMap<K1, K2> Goodies! javadoc
  • 180. // Bi-directional map, keys and values are unique BiMap<K1, K2> // Two-tier map, or a map with two keys Table<R, C, V> Goodies! javadoc
  • 181. // Bi-directional map, keys and values are unique BiMap<K1, K2> // Two-tier map, or a map with two keys Table<R, C, V> // < JDK 7, no diamond support List<String> list = Lists.newArrayList(); // Sets, Maps... Goodies! javadoc
  • 182. // Bi-directional map, keys and values are unique BiMap<K1, K2> // Two-tier map, or a map with two keys Table<R, C, V> // < JDK 7, no diamond support List<String> list = Lists.newArrayList(); // Sets, Maps... // Ranges RangeSet<Integer> rangeSet = TreeRangeSet.create(); rangeSet.add(Range.closed(1, 10)); // {[1, 10]} Goodies! javadoc
  • 183. Tons of good abstractions for you to use Bottom line
  • 184. Hashing
  • 185. Freaking PHP: md5($string) Hashing: JDK
  • 186. Freaking PHP: md5($string) public static String md5Java(String message) { String digest = null; try { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] hash = md.digest(message.getBytes("UTF-8")); String StringBuilder sb = new StringBuilder(2*hash.length); for(byte b : hash){ sb.append(String.format("%02x", b&0xff)); } digest = sb.toString(); } catch (UnsupportedEncodingException ex) { throw Throwables.propagate(ex); } catch (NoSuchAlgorithmException ex) { throw Throwables.propagate(ex); } return digest; } Hashing: JDK
  • 187. Freaking PHP: md5($string) public static String md5Java(String message) { String digest = null; try { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] hash = md.digest(message.getBytes("UTF-8")); String StringBuilder sb = new StringBuilder(2*hash.length); for(byte b : hash){ sb.append(String.format("%02x", b&0xff)); } digest = sb.toString(); } catch (UnsupportedEncodingException ex) { throw Throwables.propagate(ex); } catch (NoSuchAlgorithmException ex) { throw Throwables.propagate(ex); } return digest; } Hashing: JDK
  • 188. HashFunction hf = Hashing.md5(); Hashing: Hasher
  • 189. HashFunction hf = Hashing.md5(); HashCode hc = hf.newHasher() .putLong(id) .putString(name, Charsets.UTF_8) .putObject(person, personFunnel) .hash(); Hashing: Hasher
  • 190. HashFunction hf = Hashing.md5(); HashCode hc = hf.newHasher() .putLong(id) .putString(name, Charsets.UTF_8) .putObject(person, personFunnel) // Defines how to hash .hash(); Hashing: Hasher
  • 191. HashFunction hf = Hashing.md5(); HashCode hc = hf.newHasher() .putLong(id) .putString(name, Charsets.UTF_8) // HINT: remember this! .putObject(person, personFunnel) .hash(); Hashing: Hasher
  • 192. HashFunction hf = Hashing.md5(); HashCode hc = hf.newHasher() .putLong(id) .putString(name, Charsets.UTF_8) .putObject(person, personFunnel) .hash(); hc.asBytes(); // byte[] hc.asInt(); // value in little-endian order hc.toString(); // hexadecimal in lower case Hashing: Hasher
  • 193. // More hash functions! Hashing.md5(); Hashing.murmur3_32(); Hashing.murmur3_128(); Hashing.sha1(); Hashing.sha256(); Hashing.sha512(); Goodies! javadoc
  • 194. // More hash functions! Hashing.md5(); Hashing.murmur3_32(); Hashing.murmur3_128(); Hashing.sha1(); Hashing.sha256(); Hashing.sha512(); // Bloom Filter public boolean mightContain(T); if true, T is probably there if false, T for sure is not there Goodies! javadoc
  • 195. I/O
  • 196. Binary encoding scheme, RFC 4648 I/O: BaseEncoding
  • 197. Binary encoding scheme, RFC 4648 -- Serious stuff I/O: BaseEncoding
  • 198. Binary encoding scheme, RFC 4648 BaseEncoding .base32() .encode("foo".getBytes(Charsets.US_ASCII)); I/O: BaseEncoding
  • 199. Binary encoding scheme, RFC 4648 BaseEncoding .base32() .encode("foo".getBytes(Charsets.US_ASCII)); // returns MZXW6=== I/O: BaseEncoding
  • 200. Binary encoding scheme, RFC 4648 BaseEncoding .base32() .encode("foo".getBytes(Charsets.US_ASCII)); // returns MZXW6=== byte[] decoded = BaseEncoding .base32() .decode("MZXW6==="); I/O: BaseEncoding
  • 201. Binary encoding scheme, RFC 4648 BaseEncoding .base32() .encode("foo".getBytes(Charsets.US_ASCII)); // returns MZXW6=== byte[] decoded = BaseEncoding .base32() .decode("MZXW6==="); // returns the ASCII bytes of String “foo” I/O: BaseEncoding
  • 202. // More schemas BaseEncoding.base16(); BaseEncoding.base32(); BaseEncoding.base64(); BaseEncoding.base64Url(); // Useful all the time Goodies! javadoc
  • 203. KIA
  • 204. KIA Caches EventBus
  • 205. KIA Caches Networking EventBus Concurrency
  • 206. KIA Caches Networking Math EventBus Concurrency More I/O
  • 207. KIA Caches Networking Math Reflection EventBus Concurrency More I/O Collect
  • 208. KIA Caches Networking Math Reflection Primitives EventBus Concurrency More I/O Collect Grumpy
  • 209. Your friends Wiki
  • 210. Your friends Wiki javadoc
  • 211. Remember The “wheel”
  • 212. Remember Read this code
  • 213. Remember No Grumpy Cats were harmed in the making of this presentation
  • 214. Thanks! jordi@donky.org @jordi9
  • 215. Q & A jordi@donky.org @jordi9