SlideShare a Scribd company logo
1 of 216
Download to read offline
Google Guava
Core libraries for Java & Android
@jordi9
11 / 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
@Google
95% 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 import
import 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 &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 bag
Just like a Set<E> with repeated values
Collections: Multiset<E>
A bag
Just like a Set<E> with repeated values
You’ve done this with ArrayList<E> or Map<E, Integer>
Collections: Multiset<E>
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>
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>
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>
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>
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>
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
A Map<K, V> with multiple values
Collections: Multimap<K, V>
A Map<K, V> with multiple values
You’ve done this with Map<K, List<V>>
Collections: Multimap<K, V>
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>
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>
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>
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
// 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
KIA
Caches EventBus
KIA
Caches
Networking
EventBus
Concurrency
KIA
Caches
Networking
Math
EventBus
Concurrency
More I/O
KIA
Caches
Networking
Math
Reflection
EventBus
Concurrency
More I/O
Collect
KIA
Caches
Networking
Math
Reflection
Primitives
EventBus
Concurrency
More I/O
Collect
Grumpy
Your friends
Wiki
Your friends
Wiki
javadoc
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

More Related Content

What's hot

Google Guava & EMF @ GTUG Nantes
Google Guava & EMF @ GTUG NantesGoogle Guava & EMF @ GTUG Nantes
Google Guava & EMF @ GTUG Nantes
mikaelbarbero
 
Stuff you didn't know about action script
Stuff you didn't know about action scriptStuff you didn't know about action script
Stuff you didn't know about action script
Christophe Herreman
 
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloadingRiga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Anton Arhipov
 

What's hot (20)

Google Guava & EMF @ GTUG Nantes
Google Guava & EMF @ GTUG NantesGoogle Guava & EMF @ GTUG Nantes
Google Guava & EMF @ GTUG Nantes
 
The Groovy Puzzlers – The Complete 01 and 02 Seasons
The Groovy Puzzlers – The Complete 01 and 02 SeasonsThe Groovy Puzzlers – The Complete 01 and 02 Seasons
The Groovy Puzzlers – The Complete 01 and 02 Seasons
 
Java 8 Puzzlers [as presented at OSCON 2016]
Java 8 Puzzlers [as presented at  OSCON 2016]Java 8 Puzzlers [as presented at  OSCON 2016]
Java 8 Puzzlers [as presented at OSCON 2016]
 
Scala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldScala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 World
 
JEEConf 2017 - Having fun with Javassist
JEEConf 2017 - Having fun with JavassistJEEConf 2017 - Having fun with Javassist
JEEConf 2017 - Having fun with Javassist
 
Java Generics
Java GenericsJava Generics
Java Generics
 
Stuff you didn't know about action script
Stuff you didn't know about action scriptStuff you didn't know about action script
Stuff you didn't know about action script
 
Programming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Programming Java - Lection 07 - Puzzlers - Lavrentyev FedorProgramming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Programming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
 
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptProgrammation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScript
 
Jquery 1.3 cheatsheet_v1
Jquery 1.3 cheatsheet_v1Jquery 1.3 cheatsheet_v1
Jquery 1.3 cheatsheet_v1
 
Jquery 13 cheatsheet_v1
Jquery 13 cheatsheet_v1Jquery 13 cheatsheet_v1
Jquery 13 cheatsheet_v1
 
Scala in practice
Scala in practiceScala in practice
Scala in practice
 
Let the type system be your friend
Let the type system be your friendLet the type system be your friend
Let the type system be your friend
 
Programming Java - Lection 04 - Generics and Lambdas - Lavrentyev Fedor
Programming Java - Lection 04 - Generics and Lambdas - Lavrentyev FedorProgramming Java - Lection 04 - Generics and Lambdas - Lavrentyev Fedor
Programming Java - Lection 04 - Generics and Lambdas - Lavrentyev Fedor
 
Kotlin collections
Kotlin collectionsKotlin collections
Kotlin collections
 
Ian 20150116 java script oop
Ian 20150116 java script oopIan 20150116 java script oop
Ian 20150116 java script oop
 
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloadingRiga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
 
[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵
[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵
[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵
 
Functional Programming In Java
Functional Programming In JavaFunctional Programming In Java
Functional Programming In Java
 
Collections Framework
Collections FrameworkCollections Framework
Collections Framework
 

Similar to Google Guava - Core libraries for Java & Android

Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
Seri Moth
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developers
Stoyan Stefanov
 
ぐだ生 Java入門第一回(equals hash code_tostring)
ぐだ生 Java入門第一回(equals hash code_tostring)ぐだ生 Java入門第一回(equals hash code_tostring)
ぐだ生 Java入門第一回(equals hash code_tostring)
Makoto Yamazaki
 
bullismo e scuola primaria
bullismo e scuola primariabullismo e scuola primaria
bullismo e scuola primaria
imartini
 
CouchDB on Android
CouchDB on AndroidCouchDB on Android
CouchDB on Android
Sven Haiges
 
Get started with YUI
Get started with YUIGet started with YUI
Get started with YUI
Adam Lu
 

Similar to Google Guava - Core libraries for Java & Android (20)

Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developers
 
Object-oriented Javascript
Object-oriented JavascriptObject-oriented Javascript
Object-oriented Javascript
 
Javascript Primer
Javascript PrimerJavascript Primer
Javascript Primer
 
Data Types and Processing in ES6
Data Types and Processing in ES6Data Types and Processing in ES6
Data Types and Processing in ES6
 
ぐだ生 Java入門第一回(equals hash code_tostring)
ぐだ生 Java入門第一回(equals hash code_tostring)ぐだ生 Java入門第一回(equals hash code_tostring)
ぐだ生 Java入門第一回(equals hash code_tostring)
 
PHP Language Trivia
PHP Language TriviaPHP Language Trivia
PHP Language Trivia
 
Say It With Javascript
Say It With JavascriptSay It With Javascript
Say It With Javascript
 
bullismo e scuola primaria
bullismo e scuola primariabullismo e scuola primaria
bullismo e scuola primaria
 
The Future of JVM Languages
The Future of JVM Languages The Future of JVM Languages
The Future of JVM Languages
 
F[4]
F[4]F[4]
F[4]
 
Grails Launchpad - From Ground Zero to Orbit
Grails Launchpad - From Ground Zero to OrbitGrails Launchpad - From Ground Zero to Orbit
Grails Launchpad - From Ground Zero to Orbit
 
CouchDB on Android
CouchDB on AndroidCouchDB on Android
CouchDB on Android
 
Presentatie - Introductie in Groovy
Presentatie - Introductie in GroovyPresentatie - Introductie in Groovy
Presentatie - Introductie in Groovy
 
JavaScript - i och utanför webbläsaren (2010-03-03)
JavaScript - i och utanför webbläsaren (2010-03-03)JavaScript - i och utanför webbläsaren (2010-03-03)
JavaScript - i och utanför webbläsaren (2010-03-03)
 
Realm: Building a mobile database
Realm: Building a mobile databaseRealm: Building a mobile database
Realm: Building a mobile database
 
Get started with YUI
Get started with YUIGet started with YUI
Get started with YUI
 
jQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journeyjQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journey
 
Wakanday JS201 Best Practices
Wakanday JS201 Best PracticesWakanday JS201 Best Practices
Wakanday JS201 Best Practices
 
Kotlin for Android Developers - Victor Kropp - Codemotion Rome 2018
Kotlin for Android Developers - Victor Kropp - Codemotion Rome 2018Kotlin for Android Developers - Victor Kropp - Codemotion Rome 2018
Kotlin for Android Developers - Victor Kropp - Codemotion Rome 2018
 

More from Jordi Gerona (7)

Netty from the trenches
Netty from the trenchesNetty from the trenches
Netty from the trenches
 
Clean code via dependency injection + guice
Clean code via dependency injection + guiceClean code via dependency injection + guice
Clean code via dependency injection + guice
 
Unit Testing - Trovit
Unit Testing - TrovitUnit Testing - Trovit
Unit Testing - Trovit
 
Mitos y otras criaturas startuperas (webbar)
Mitos y otras criaturas startuperas (webbar)Mitos y otras criaturas startuperas (webbar)
Mitos y otras criaturas startuperas (webbar)
 
Mercurial
MercurialMercurial
Mercurial
 
Unit Testing - GTUG
Unit Testing - GTUGUnit Testing - GTUG
Unit Testing - GTUG
 
Dependency Injection con Guice - GTUG
Dependency Injection con Guice - GTUGDependency Injection con Guice - GTUG
Dependency Injection con Guice - GTUG
 

Recently uploaded

EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 

Recently uploaded (20)

08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 

Google Guava - Core libraries for Java & Android