Google Guava - Core libraries for Java & Android

Preview:

DESCRIPTION

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.

Citation preview

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();

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);

// 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 &gt; bar

Escapers

HtmlEscapers.htmlEscaper().escape("Foo > bar");

XmlEscapers.xmlAttributeEscaper().escape("foo \"bar\"");

// returns foo &quot;bar&quot;

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

Remember

The “wheel”

Remember

Read this code

Remember

No Grumpy Cats were harmed in the making of

this presentation

Thanks!

jordi@donky.org@jordi9

Q & A

jordi@donky.org@jordi9

Recommended