Date post: | 08-Sep-2014 |
Category: |
Technology |
Upload: | jordi-gerona |
View: | 5,539 times |
Download: | 3 times |
Google GuavaCore libraries for Java & Android
@jordi911 / oct / 2013
...shameless self-promotion bro!
Write less code
Write cleaner code
Write more readable code
The “wheel”
com.google.guava:guava:15.0
Basics
Basics
Avoid using null
Basics: Avoid using null
“Null sucks”
Doug Lea - JCP, OpenJDK
Basics: Avoid using null
“I call it my billion-dollar mistake”
Sir C.A.R. Hoare - Inventor of null
Basics: Avoid using null
@Google95% of collections weren’t supposed to have null values.
map = {Foo: bar, null, Baz: qux}
Basics: Avoid using null
map = {Foo: bar, null, Baz: qux}
map.get(“Foo”);
Basics: Avoid using null
map = {Foo: bar, null, Baz: qux}
map.get(“Foo”); // returns Foo
Basics: Avoid using null
map = {Foo: bar, null, Baz: qux}
map.get(“Foo”);
map.get(“quux”);
Basics: Avoid using null
map = {Foo: bar, null, Baz: qux}
map.get(“Foo”);
map.get(“quux”); // returns null
Basics: Avoid using null
map = {Foo: bar, null, Baz: qux}
map.get(“Foo”);
map.get(“quux”);
map.get(null);
Basics: Avoid using null
map = {Foo: bar, null, Baz: qux}
map.get(“Foo”);
map.get(“quux”);
map.get(null); // returns null
Basics: Avoid using null
map = {Foo: bar, null, Baz: qux}
map.get(“Foo”);
map.get(“quux”); // returns null
map.get(null); // returns null
Basics: Avoid using null
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
Optional<T>
Basics: Avoid using null
Optional<T>
Optional<String> foo = Optional.of(“foo”)
Basics: Avoid using null
Optional<T>
Optional<String> foo = Optional.of(“foo”)
foo.isPresent(); // returns true
Basics: Avoid using null
Optional<T>
Optional<String> foo = Optional.of(“foo”)
foo.isPresent();
foo.get(); // returns “foo”
Basics: Avoid using null
Optional.of(foo); // not nullable
Goodies!
RTFM, I mean javadoc
Optional.of(foo);
Optional.absent();
Goodies!
javadoc
Optional.of(foo);
Optional.absent();
Optional.fromNullable(legacyCode);
Goodies!
javadoc
Optional.of(foo);
Optional.absent();
Optional.fromNullable(legacyCode);
foo.get(); // may return “foo”
Goodies!
javadoc
Optional.of(foo);
Optional.absent();
Optional.fromNullable(legacyCode);
foo.get();
foo.or(“bar”); // return “bar” if foo is absent
Goodies!
javadoc
Optional.of(foo);
Optional.absent();
Optional.fromNullable(legacyCode);
foo.get();
foo.or(“bar”);
foo.orNull(); // Deal with code that need nulls, duh
Goodies!
javadoc
Optional<T> is IDIOT-PROOF-NESS
Bottom line
Basics
Preconditions
if (seats <= 0) {
throw new IllegalArgumentException(“Seats must be
positive, but was ” + seats);
}
Basics: Preconditions
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
// Always use static importimport static com.google.common.base.Preconditions.checkArgument;
checkArgument(seats > 0, “Seats must be positive,
but was %s”, seats);
Basics: Preconditions
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
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
void execute(Job job) {
// serious business
}
Basics: Preconditions
void execute(Job job) {
checkNotNull(job, “Job can’t be null”);
// serious business
}
// checkNotNull() throws NullPointerException
Basics: Preconditions
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
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
this.foo = checkNotNull(foo); // inline assig
Goodies!
javadoc
this.foo = checkNotNull(foo);
// list, string or array checks
checkElementIndex(index, size);
checkPositionIndex(index, size);
checkPositionIndexes(start, end, size);
Goodies!
javadoc
Preconditions will save your ass
Bottom line
Basics
Objects
@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
@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
@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
@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
@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
@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
@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
@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
@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
@Override
public int hashCode() {
return Objects.hashCode(firstName, lastName);
}
Basics: Objects
@Override
public int hashCode() {
// sensible, order-sensitive hash
return Objects.hashCode(firstName, lastName);
}
Basics: Objects
@Override
public int hashCode() {
return Objects.hashCode(firstName, lastName);
}
// JDK 1.7 introduced equivalent Objects.hash() method.
Basics: Objects
@Override
public String toString() {
}
Basics: Objects
@Override
public String toString() {
}
Basics: Objects
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("firstName", firstName)
.add("lastName", lastName)
.add("catName", catName)
.toString();
}
Basics: Objects
@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
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("firstName", firstName)
.add("lastName", lastName)
.add("catName", catName)
.omitNullValues()
.toString();
}
Basics: Objects
@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
IntelliJ IDEA support for ToStringHelper() Generate toString() > Template Objects.ToStringHelper (Guava)
Goodies!
javadoc
So common stuff should ring a bell
Bottom line
Basics
Ordering
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
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
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
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
Comparator<Person> byDescAgeName =
Ordering.natural()
.reverse()
.onResultOf(new Function<Person, Integer>() {
public Integer apply(Person person) {
return person.getAge();
}})
.compound(Ordering.natural());
}
};
Basics: Ordering
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
Ordering is an “enriched” Comparator. It’s fuuuuuuuun!
Goodies!
javadoc
Ordering is an “enriched” Comparator. It’s fluent.
Goodies!
javadoc
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
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
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
There’s a better way than Comparator
Bottom line
Basics
Throwables
void oneLineOfCode() {
DatagramPacket packet = new DatagramPacket(data, length);
}
Basics: Throwables
void oneLineOfCode() {
DatagramPacket packet = new DatagramPacket(data, length);
}
// Compile error, throws IOException
Basics: Throwables
void oneLineOfCode() throws IOException {
DatagramPacket packet = new DatagramPacket(data, length);
}
void someLayer() {
oneLineOfCode();
}
Basics: Throwables
void oneLineOfCode() throws IOException {
DatagramPacket packet = new DatagramPacket(data, length);
}
void someLayer() {
oneLineOfCode();
}
// Compile error, throws IOException
Basics: Throwables
void oneLineOfCode() throws IOException {
DatagramPacket packet = new DatagramPacket(data, length);
}
void someLayer() throws IOException {
oneLineOfCode();
}
void someCoolAbstraction() {
someLayer();
}
Basics: Throwables
void oneLineOfCode() throws IOException {
DatagramPacket packet = new DatagramPacket(data, length);
}
void someLayer() throws IOException {
oneLineOfCode();
}
void someCoolAbstraction() {
someLayer();
}
// Compile error, AGAIN
Basics: Throwables
void oneLineOfCode() throws IOException {
DatagramPacket packet = new DatagramPacket(data, length);
}
void someLayer() throws IOException {
oneLineOfCode();
}
void someCoolAbstraction() throws IOException {
someLayer();
}
Basics: Throwables
void oneLineOfCode() throws IOException {
DatagramPacket packet = new DatagramPacket(data, address);
}
void someLayer() throws IOException {
oneLineOfCode();
}
void someCoolAbstraction() throws IOException {
someLayer();
}
// c’mon...
Basics: Throwables
void oneLineOfCode() {
// Take 2
DatagramPacket packet = new DatagramPacket(data, length);
}
Basics: Throwables
void oneLineOfCode() {
try {
DatagramPacket packet = new DatagramPacket(data, length);
} catch (IOException e) {
}
}
Basics: Throwables
void oneLineOfCode() {
try {
DatagramPacket packet = new DatagramPacket(data, length);
} catch (IOException e) {
// Really? Swallow? Sure? At least explain why!
}
}
Basics: Throwables
void oneLineOfCode() {
try {
DatagramPacket packet = new DatagramPacket(data, length);
} catch (IOException e) {
SendMeAnEmail.error();
}
}
Basics: Throwables
void oneLineOfCode() {
try {
DatagramPacket packet = new DatagramPacket(data, length);
} catch (IOException e) {
SendMeAnEmail.error();
Oh.theLogger().fatal(“WHY Y U FATAL NOW?”);
}
}
Basics: Throwables
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
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
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
void oneLineOfCode() {
// Take 3
DatagramPacket packet = new DatagramPacket(data, length);
}
Basics: Throwables
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
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
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
// more forms
propagateIfInstanceOf(throwable,exceptionClass);
Goodies… or gotcha’s!
javadoc
// more forms
propagateIfInstanceOf(throwable,exceptionClass);
propagateIfPossible(throwable); // Only if RuntimeException or Error
Goodies… or gotcha’s!
javadoc
// more forms
propagateIfInstanceOf(throwable,exceptionClass);
propagateIfPossible(throwable);
propagateIfPossible(throwable, exceptionClass);
Goodies… or gotcha’s!
javadoc
// more forms
propagateIfInstanceOf(throwable,exceptionClass);
propagateIfPossible(throwable);
propagateIfPossible(throwable, exceptionClass);
General practice: Convert checked exceptions to unchecked exceptions
Goodies… or gotcha’s!
javadoc
// 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
// 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
Think your fraking Exceptions
Bottom line
Strings
Strings
Splitter
We have String.split bro!
Strings: Splitter
We have String.split bro!
“,f,,o, o,”.split(“,”) returns:
Strings: Splitter
We have String.split bro!
“,f,,o, o,”.split(“,”) returns:
a. [“”, “f”, “”, “o”, “ o”,””]
Strings: Splitter
We have String.split bro!
“,f,,o, o,”.split(“,”) returns:
a. [“”, “f”, “”, “o”, “ o”,””]
b. [null, “f”, null, “o” ,”o”, null]
Strings: Splitter
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
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
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
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
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
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
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
“,f,,o, o,”.split(“,”) we probably want [“f”,”o”,”o”]
Strings: Splitter
“,f,,o, o,”.split(“,”) we probably want [“f”,”o”,”o”]
Splitter.on(‘,’)
.split(“,f,,o, o,”);
Strings: Splitter
“,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
“,f,,o, o,”.split(“,”) we probably want [“f”,”o”,”o”]
Splitter.on(‘,’)
.omitEmptyStrings()
.split(“,f,,o, o,”);
Strings: Splitter
“,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
“,f,,o, o,”.split(“,”) we probably want [“f”,”o”,”o”]
Splitter.on(‘,’)
.omitEmptyStrings()
.trimResults()
.split(“,f,,o, o,”);
Strings: Splitter
“,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
“,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
Strings
Joiner
[“Jack, “Chloe”, “Tony”, null, “Nina”, “Logan”]
Strings: Joiner
[“Jack, “Chloe”, “Tony”, null, “Nina”, “Logan”]
Joiner.on(“, “)
.join(twentyFour);
Strings: Joiner
[“Jack, “Chloe”, “Tony”, null, “Nina”, “Logan”]
Joiner.on(“, “)
.join(twentyFour);
// throws NullPointerException!
Strings: Joiner
[“Jack, “Chloe”, “Tony”, null, “Nina”, “Logan”]
Joiner.on(“, “)
.join(twentyFour);
// throws NullPointerException!
// null-hostile operations everywhere, good thing ;)
Strings: Joiner
[“Jack, “Chloe”, “Tony”, null, “Nina”, “Logan”]
Joiner.on(“, “)
.skipNulls();
.join(twentyFour);
// returns “Jack, Chloe, Tony, Nina, Logan”
Strings: Joiner
[“Jack, “Chloe”, “Tony”, null, “Nina”, “Logan”]
Joiner.on(“, “)
.useForNull(“Bill”);
.join(twentyFour);
// returns “Jack, Chloe, Tony, Bill, Nina, Logan”
Strings: Joiner
javadoc
Always think how to avoid null-idioty
Bottom line
Strings
CharMatcher
Your StringUtils replacement
Strings: CharMatcher
Your StringUtils replacement
CharMatcher.JAVA_ISO_CONTROL.removeFrom(string); // remove control chars
Strings: CharMatcher
Your StringUtils replacement
CharMatcher.JAVA_ISO_CONTROL.removeFrom(string);
CharMatcher.DIGIT.retainFrom(“jordi9”); // returns 9
Strings: CharMatcher
Your StringUtils replacement
CharMatcher.JAVA_ISO_CONTROL.removeFrom(string);
CharMatcher.DIGIT.retainFrom(“jordi9”);
CharMatcher.DIGIT.removeFrom(“jordi9”); // returns jordi
Strings: CharMatcher
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
// 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
// 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
Strings
Escapers
HtmlEscapers.htmlEscaper().escape("Foo > bar");
// returns Foo > bar
Escapers
HtmlEscapers.htmlEscaper().escape("Foo > bar");
XmlEscapers.xmlAttributeEscaper().escape("foo \"bar\"");
// returns foo "bar"
Escapers
HtmlEscapers.htmlEscaper().escape("Foo > bar");
XmlEscapers.xmlAttributeEscaper().escape("foo \"bar\"");
XmlEscapers.xmlContentEscaper().escape("foo \"bar\"");
// returns foo “bar”
Escapers
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
Collections
Collections: Functional Idiom
Collections: Functional Idiom
Collections: Functional Idiom
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
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
Multiset<Integer> lengths = HashMultiset.create();
for (String string : strings) {
if (CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string)) {
lengths.add(string.length());
}
}
Collections: Functional Idiom
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
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
Immutable = Thread-safe
Collections: Immutable types
Immutable = Thread-safe
static final ImmutableSet<String> FOO_NAMES =
ImmutableSet.of(“foo”, “bar”, “baz”);
Collections: Immutable types
Immutable = Thread-safe
static final ImmutableSet<String> FOO_NAMES =
ImmutableSet.of(“foo”, “bar”, “baz”);
// ImmutableList, ImmutableMap...
Collections: Immutable types
Immutable = Thread-safe
static final ImmutableSet<String> FOO_NAMES =
ImmutableSet.of(“foo”, “bar”, “baz”);
ImmutableList<String> defensiveCopy =
ImmutableList.copyOf(someList);
Collections: Immutable types
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
A bag
Collections: Multiset<E>
A bagJust like a Set<E> with repeated values
Collections: Multiset<E>
A bagJust like a Set<E> with repeated valuesYou’ve done this with ArrayList<E> or Map<E, Integer>
Collections: Multiset<E>
A bagJust like a Set<E> with repeated valuesYou’ve done this with ArrayList<E> or Map<E, Integer>
Multiset<Person> ppl = HashMultiset.create();
Collections: Multiset<E>
A bagJust like a Set<E> with repeated valuesYou’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>
A bagJust like a Set<E> with repeated valuesYou’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>
A bagJust like a Set<E> with repeated valuesYou’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>
A bagJust like a Set<E> with repeated valuesYou’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>
A bagJust like a Set<E> with repeated valuesYou’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
A Map<K, V> with multiple values
Collections: Multimap<K, V>
A Map<K, V> with multiple valuesYou’ve done this with Map<K, List<V>>
Collections: Multimap<K, V>
A Map<K, V> with multiple valuesYou’ve done this with Map<K, List<V>>
Multimap<Person, Ticket> ticketsByPerson =
ArrayListMultimap.create();
Collections: Multimap<K, V>
A Map<K, V> with multiple valuesYou’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>
A Map<K, V> with multiple valuesYou’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>
A Map<K, V> with multiple valuesYou’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
// Bi-directional map, keys and values are unique
BiMap<K1, K2>
Goodies!
javadoc
// 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
// 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
// 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
Tons of good abstractions for you to use
Bottom line
Hashing
Freaking PHP: md5($string)
Hashing: JDK
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
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
HashFunction hf = Hashing.md5();
Hashing: Hasher
HashFunction hf = Hashing.md5();
HashCode hc = hf.newHasher()
.putLong(id)
.putString(name, Charsets.UTF_8)
.putObject(person, personFunnel)
.hash();
Hashing: Hasher
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
HashFunction hf = Hashing.md5();
HashCode hc = hf.newHasher()
.putLong(id)
.putString(name, Charsets.UTF_8) // HINT: remember this!
.putObject(person, personFunnel)
.hash();
Hashing: Hasher
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
// More hash functions!
Hashing.md5();
Hashing.murmur3_32();
Hashing.murmur3_128();
Hashing.sha1();
Hashing.sha256();
Hashing.sha512();
Goodies!
javadoc
// 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
I/O
Binary encoding scheme, RFC 4648
I/O: BaseEncoding
Binary encoding scheme, RFC 4648 -- Serious stuff
I/O: BaseEncoding
Binary encoding scheme, RFC 4648
BaseEncoding
.base32()
.encode("foo".getBytes(Charsets.US_ASCII));
I/O: BaseEncoding
Binary encoding scheme, RFC 4648
BaseEncoding
.base32()
.encode("foo".getBytes(Charsets.US_ASCII));
// returns MZXW6===
I/O: BaseEncoding
Binary encoding scheme, RFC 4648
BaseEncoding
.base32()
.encode("foo".getBytes(Charsets.US_ASCII));
// returns MZXW6===
byte[] decoded = BaseEncoding
.base32()
.decode("MZXW6===");
I/O: BaseEncoding
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
// More schemas
BaseEncoding.base16();
BaseEncoding.base32();
BaseEncoding.base64();
BaseEncoding.base64Url(); // Useful all the time
Goodies!
javadoc
KIA
KIACaches EventBus
KIACachesNetworking
EventBusConcurrency
KIACachesNetworkingMath
EventBusConcurrencyMore I/O
KIACachesNetworkingMathReflection
EventBusConcurrencyMore I/O Collect
KIACachesNetworkingMathReflectionPrimitives
EventBusConcurrencyMore I/O Collect Grumpy
Your friends
Wiki
javadoc
Remember
The “wheel”
Remember
Read this code
Remember
No Grumpy Cats were harmed in the making of
this presentation