Contenu connexe Similaire à Guava au Paris JUG (20) Plus de Thierry Leriche-Dessirier (20) Guava au Paris JUG1. 08/11/2011
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
2. 08/11/2011
Guava by Google
Thierry Leriche
Consultant freelance
ICAUDA
Etienne Neveu
Consultant
SFEIR
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
4. Factory Methods
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
4
5. Factory Methods
Avec Java 5
List<Integer> primeNumbers = new ArrayList<Integer>();
Set<String> colors = new TreeSet<String>();
Map<String, Integer> ages = new HashMap<String, Integer>();
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
5
6. Factory Methods
Avec Java 5
List<Integer> primeNumbers = new ArrayList<Integer>();
Set<String> colors = new TreeSet<String>();
Map<String, Integer> ages = new HashMap<String, Integer>();
ou même...
Map<String, List<String>> favoriteColors
= new HashMap<String, List<String>>();
Map<? extends Person, Map<String, List<String>>> favoriteColors
= new TreeMap<? Extends Person, Map<String, List<String>>>();
on peut facilement trouver pire...
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
6
7. Factory Methods
Avec Java 5
List<Integer> primeNumbers = new ArrayList<Integer>();
Set<String> colors = new TreeSet<String>();
Map<String, Integer> ages = new HashMap<String, Integer>();
Avec Java 7
List<Integer> primeNumbers = new ArrayList<>();
Set<String> colors = new TreeSet<>();
Map<String, Integer> ages = new HashMap<>();
mais quand ?
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
7
8. Factory Methods
Avec Java 5
List<Integer> primeNumbers = new ArrayList<Integer>();
Set<String> colors = new TreeSet<String>();
Map<String, Integer> ages = new HashMap<String, Integer>();
Avec Java 7
List<Integer> primeNumbers = new ArrayList<>();
Set<String> colors = new TreeSet<>();
Map<String, Integer> ages = new HashMap<>();
Avec Guava
List<Integer> primeNumbers = newArrayList();
Set<String> colors = newTreeSet();
Map<String, Integer> ages = newHashMap();
tout de suite
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
8
9. Factory Methods
Par exemple, avec des chiens
public class Dog {
private String name;
private Double weight;
private Sex sex;
public Dog(String name, Sex sex) {
this.name = name ;
this.sex = sex;
}
// getters & setters
}
public enum Sex {
MALE, FEMALE
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
9
10. Factory Methods
Par exemple, avec des chiens
List<Dog> dogs = newArrayList();
dogs.add(new Dog("Milou", MALE));
dogs.add(new Dog("Idefix", MALE));
dogs.add(new Dog("Lassie", FEMALE));
dogs.add(new Dog("Rintintin", MALE));
dogs.add(new Dog("Lady", FEMALE));
dogs.add(new Dog("Medor", MALE));
08/11/2011
Guava by Google
Milou
Idefix
Lassie
Rintintin
Lady
Medor
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
10
11. Factory Methods
Ou plutôt
List<Dog> dogs = newArrayList(
new Dog("Milou", MALE),
new Dog("Idefix", MALE),
new Dog("Lassie", FEMALE),
new Dog("Rintintin", MALE),
new Dog("Lady", FEMALE),
new Dog("Medor", MALE)
);
08/11/2011
Guava by Google
Milou
Idefix
Lassie
Rintintin
Lady
Medor
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
11
12. Functional Programming
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
12
13. Functional Programming
Filtre avec Predicate
Iterable<Dog> maleDogs = Iterables.filter(dogs,
new Predicate<Dog>() {
public boolean apply(Dog dog) {
return dog.getSex() == MALE;
}
});
Milou
Idefix
prog fonc ? Rintintin
Medor
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
13
14. Functional Programming
And, or, in, not, ...
List<Dog> superDogs = newArrayList(
new Dog("Milou", MALE),
new Dog("Lassie", FEMALE),
new Dog("Volt", MALE));
08/11/2011
Guava by Google
Milou
Lassie
Volt
Milou
Idefix
Lassie
Rintintin
Lady
Medor
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
14
15. Functional Programming
And, or, in, not, ...
List<Dog> superDogs = newArrayList(
new Dog("Milou", MALE),
new Dog("Lassie", FEMALE),
new Dog("Volt", MALE));
boolean isMilouInBoth
= and(in(dogs), in(superDogs))
.apply(new Dog("Milou"));
boolean isTintinInOne
= or(in(dogs), in(superDogs))
.apply(new Dog("Tintin"));
08/11/2011
Guava by Google
Milou
Lassie
Volt
Milou
Idefix
Lassie
Rintintin
Lady
Medor
true
false
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
15
16. Functional Programming
Un chien en français
public class Chien {
private String prenom;
public Chien(String prenom) {
this.prenom = prenom;
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
16
17. Functional Programming
Transformation
List<Chien> chiens =
Lists.transform(dogs, new Function<Dog, Chien>() {
public Chien apply(Dog dog) {
return new Chien(dog.getName());
}
});
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
17
18. Functional Programming
Attention : vue
List<Chien> chiens =
Lists.transform(dogs, new Function<Dog, Chien>() {
public Chien apply(Dog dog) {
return new Chien(dog.getName());
}
});
–
Vue (lazy)
–
size / isEmpty dispo
–
Pas fait pour des traitements multiples
List<Chien> chiens = newArrayList(Lists.transform(...
ImmutableList<Chien> chiens
= ImmutableList.copyOf(Lists.transform(...
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
18
19. Functional Programming
Converter Spring
import org.springframework...Converter;
@Component("dogToChienConverter")
public class DogToChienConverter
implements Converter<List<Dog>, List<Chien>> {
public List<Chien> convert(List<Dog> dogs) {
List<Chien> chiens = newArrayList(Lists.transform(dogs,
new Function<Dog, Chien>() {
public Chien apply(Dog dog) {
return new Chien(dog.getName());
}
}));
}
return chiens;
Lazy or not lazy ?
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
19
20. Functional Programming
Find
Predicate<Dog> malePredicate = new Predicate<Dog>() {
public boolean apply(Dog dog) {
return dog.getSex() == MALE;
}};
Dog firstMale = Iterables.find(dogs, malePredicate);
Milou
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
20
21. Functional Programming
Find
Predicate<Dog> malePredicate = new Predicate<Dog>() {
public boolean apply(Dog dog) {
return dog.getSex() == MALE;
}};
Dog firstMale = Iterables.find(dogs, malePredicate);
Milou
Dog firstMale = Iterables.find(femaleDogs, malePredicate, DEFAULT_DOG );
Chien par défaut
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
21
22. Immutable Collections
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
22
23. Immutable Collections
Set (en Java)
Set<Integer> temp = new LinkedHashSet<Integer>(
Arrays.asList(1, 2, 3, 5, 7));
Set<Integer> primeNumbers = Collections.unmodifiableSet(temp);
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
23
24. Immutable Collections
Set (en Java) Vs ImmutableSet (Guava)
Set<Integer> temp = new LinkedHashSet<Integer>(
Arrays.asList(1, 2, 3, 5, 7));
Set<Integer> primeNumbers = Collections.unmodifiableSet(temp);
Guava
Set<Integer> primeNumbers = ImmutableSet.of(1, 2, 3, 5, 7);
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
24
25. Immutable Collections
Multi « of »
ImmutableSet.of(E
ImmutableSet.of(E
ImmutableSet.of(E
ImmutableSet.of(E
ImmutableSet.of(E
ImmutableSet.of(E
e1)
e1,
e1,
e1,
e1,
e1,
E
E
E
E
E
e2)
e2,
e2,
e2,
e2,
E
E
E
E
e3)
e3, E e4)
e3, E e4, E e5)
e3, E e4, E e5, E e6, E...)
n'accepte pas les éléments null
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
25
26. Immutable Collections
Multi « of »
ImmutableSet.of(E
ImmutableSet.of(E
ImmutableSet.of(E
ImmutableSet.of(E
ImmutableSet.of(E
ImmutableSet.of(E
e1)
e1,
e1,
e1,
e1,
e1,
E
E
E
E
E
e2)
e2,
e2,
e2,
e2,
E
E
E
E
e3)
e3, E e4)
e3, E e4, E e5)
e3, E e4, E e5, E e6, E...)
n'accepte pas les éléments null
ImmutableSet.of()
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
26
27. Immutable Collections
Copie de défense (en java)
public class Person {
private final Set<String> favoriteColors;
private final String firstName;
public Person(Set<String> favoriteColors, String firstName) {
this.favoriteColors = Collections.unmodifiableSet(
new LinkedHashSet<String>(favoriteColors));
this.firstName = firstName;
}
public Set<String> getFavoriteColors() {
return favoriteColors;
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
27
28. Immutable Collections
Copie de défense (Guava)
public class Person {
private final ImmutableSet<String> favoriteColors;
private final String firstName;
public Person(Set<String> favoriteColors, String firstName) {
this.favoriteColors = ImmutableSet.copyOf(favoriteColors));
}
this.firstName = firstName;
public ImmutableSet<String> getFavoriteColors() {
return favoriteColors;
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
28
29. Base – Objects
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
29
30. Base – Objects
Le retour du chien
public class Dog {
private String name;
private Double weight;
private Sex sex;
public Dog(String name, Sex sex) {
this.name = name ;
this.sex = sex;
}
// getters & setters
}
public enum Sex {
MALE, FEMALE
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
30
31. Base – Objects
Objects.equal()
public boolean equals(Object other) {
if (!(other instanceof Dog)) return false;
Dog that = (Dog) other;
}
return
(name == that.name
|| (name != null && name.equals(that.name)))
&& (weight == that.weight
|| (weight != null && weight.equals(that.weight)))
&& sex == that.sex;
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
31
32. Base – Objects
Objects.equal()
public boolean equals(Object other) {
if (!(other instanceof Dog)) return false;
Dog that = (Dog) other;
}
return
Objects.equal(name, that.name)
&& Objects.equal(weight, that.weight)
&& sex == that.sex;
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
32
33. Base – Objects
Objects.hashCode()
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (weight != null ? weight.hashCode():0);
result = 31 * result + (sex != null ? sex.hashCode():0);
}
return result;
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
33
34. Base – Objects
Objects.hashCode()
public int hashCode() {
}
return Objects.hashCode(name, weight, sex);
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
34
35. Base – Objects
Objects.toStringHelper()
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(Dog.class.getSimpleName());
sb.append("{name=").append(name);
sb.append(", weight=").append(weight);
sb.append(", sex=").append(sex);
sb.append('}');
return sb.toString();
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
35
36. Base – Objects
Objects.toStringHelper()
public String toString() {
}
return Objects.toStringHelper(this)
.add("name", name)
.add("weight", weight)
.add("sex", sex)
.toString();
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
36
37. Base – Objects
ComparisonChain
public int compareTo(Dog other) {
int result = name.compareTo(other.name);
if (result != 0) {
return result;
}
result = weight.compareTo(other.weight);
if (result != 0) {
return result;
}
}
return sex.compareTo(other.sex);
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
37
38. Base – Objects
ComparisonChain
public int compareTo(Dog other) {
}
return ComparisonChain.start()
.compare(name, other.name)
.compare(weight, other.weight)
.compare(sex, other.sex)
.result();
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
38
39. Base – Objects
ComparisonChain
public int compareTo(Dog other) {
}
return ComparisonChain.start()
.compare(name, other.name, NULL_LAST_COMPARATOR)
.compare(weight, other.weight, NULL_LAST_COMPARATOR)
.compare(sex, other.sex, NULL_LAST_COMPARATOR)
.result();
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
39
40. Base – Preconditions
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
40
41. Base – Preconditions
Money money money
@Immutable
public class Money {
@Nonnull
private final BigDecimal amount;
@Nonnull
private final Currency currency;
public Money(BigDecimal amount, Currency currency) {
// ???
}
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
41
42. Base – Preconditions
Validation classique des arguments
public Money(BigDecimal amount, Currency currency) {
if (amount == null) {
throw new NullPointerException("amount cannot be null");
}
if (currency == null) {
throw new NullPointerException("currency cannot be null");
}
if (amount.signum() < 0) {
throw new IllegalArgumentException("must be positive: " + amount);
}
}
this.amount = amount;
this.currency = currency;
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
42
43. Base – Preconditions
Validation avec Preconditions
import static com.google.common.base.Preconditions.*;
public Money(BigDecimal amount, Currency currency) {
checkNotNull(amount, "amount cannot be null");
checkNotNull(currency, "currency cannot be null");
checkArgument(amount.signum() >= 0, "must be positive: %s", amount);
}
this.amount = amount;
this.currency = currency;
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
43
44. Base – Preconditions
Validation et assignement inline
import static com.google.common.base.Preconditions.*;
public Money(BigDecimal amount, Currency currency) {
this.amount = checkNotNull(amount, "amount cannot be null");
this.currency = checkNotNull(currency, "currency cannot be null");
checkArgument(amount.signum() >= 0, "must be positive: %s", amount);
}
public static <T> T checkNotNull(T reference) {
if (reference == null) {
throw new NullPointerException();
}
return reference;
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
44
45. Base – CharMatcher
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
45
46. Base – CharMatcher
StringUtils ?
String collapse(String source, String charsToCollapse)
String collapseWhitespace(String source)
String collapseControlChars(String source)
int
int
lastIndexOf(String source, String chars)
lastIndexNotOf(String source, String chars)
String
String
String
String
remove(String source, String charsToRemove)
removeDigits(String source)
removeWhitespace(String source)
removeControlChars(String source)
String trim(String source, String charsToStrip)
String trimWhiteSpace(String source)
String trimControlChars(String source)
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
46
47. Base – CharMatcher
StringUtils → CharMatcher
String collapse(String source, String charsToCollapse)
String collapseWhitespace(String source)
String collapseControlChars(String source)
int
int
lastIndexOf(String source, String chars)
lastIndexNotOf(String source, String chars)
String
String
String
String
remove(String source, String charsToRemove)
removeDigits(String source)
removeWhitespace(String source)
removeControlChars(String source)
String trim(String source, String charsToStrip)
String trimWhiteSpace(String source)
String trimControlChars(String source)
public abstract class CharMatcher {
public boolean matches(char c);
}
// ...
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
47
48. Base – CharMatcher
Obtention d'un CharMatcher
CharMatcher.ANY
CharMatcher.NONE
CharMatcher.ASCII
CharMatcher.DIGIT
CharMatcher.WHITESPACE
CharMatcher.JAVA_ISO_CONTROL
CharMatcher.is('x')
CharMatcher.isNot('_')
CharMatcher.anyOf('aeiou').negate()
CharMatcher.inRange('a', 'z').or(CharMatcher.inRange('A', 'Z'))
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
48
49. Base – CharMatcher
Utilisation d'un CharMatcher
boolean matchesAllOf(CharSequence)
boolean matchesAnyOf(CharSequence)
boolean matchesNoneOf(CharSequence)
int
indexIn(CharSequence, int)
int
lastIndexIn(CharSequence, int)
int
countIn(CharSequence)
String removeFrom(CharSequence)
String retainFrom(CharSequence)
String trimFrom(CharSequence)
String trimLeadingFrom(CharSequence)
String trimTrailingFrom(CharSequence)
String collapseFrom(CharSequence, char)
String trimAndCollapseFrom(CharSequence, char)
String replaceFrom(CharSequence, char)
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
49
50. Base – CharMatcher
Utilisation d'un CharMatcher
boolean matchesAllOf(CharSequence)
boolean matchesAnyOf(CharSequence)
boolean matchesNoneOf(CharSequence)
int
indexIn(CharSequence, int)
int
lastIndexIn(CharSequence, int)
int
countIn(CharSequence)
String removeFrom(CharSequence)
String retainFrom(CharSequence)
String trimFrom(CharSequence)
String trimLeadingFrom(CharSequence)
String trimTrailingFrom(CharSequence)
String collapseFrom(CharSequence, char)
String trimAndCollapseFrom(CharSequence, char)
String replaceFrom(CharSequence, char)
CharMatcher VALID_CHARS = CharMatcher.DIGIT.or(CharMatcher.anyOf(“-_”);
String VALID_CHARS.retainFrom(input);
checkArgument(!CharMatcher.WHITESPACE.matchesAllOf(input));
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
50
51. Collection Utilities
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
51
52. Collection Utilities
Multimap (avec Java)
Map<String, List<String>> favoriteColors
= new HashMap<String, List<String>>();
List<String> julienColors = favoriteColors.get("Julien");
if(julienColors == null) {
julienColors = new ArrayList<String>();
favoriteColors.put("Julien",julienColors);
}
julienColors.add("Vert");
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
52
53. Collection Utilities
Multimap (avec Guava)
Map<String, List<String>> favoriteColors
= new HashMap<String, List<String>>();
Multimap<String, String> favoriteColors = HashMultimap.create();
favoriteColors2.put("Julien", "Jaune");
favoriteColors2.put("Julien", "Rouge");
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
53
54. Collection Utilities
Bimap (Clé-Valeur-Clé)
BiMap<String, String> cars = HashBiMap.create();
cars.put("Thierry", "1234 AB 91");
cars.put("Marie", "4369 ERD 75");
cars.put("Julien", "549 DF 87");
{Thierry=1234 AB 91,
Julien=549 DF 87,
Marie=4369 ERD 75}
println(cars);
println(cars.inverse());
Une map bijective
{1234 AB 91=Thierry,
549 DF 87=Julien,
4369 ERD 75=Marie}
Il est possible de changer la valeur associée à une clé mais pas d'avoir deux clés
avec la même valeur (IllegalArgumentException).
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
54
55. Collection Utilities
Multiset
Multiset<Integer> primeNumbers = HashMultiset.create();
primeNumbers.add(2);
primeNumbers.add(3);
primeNumbers.add(7);
primeNumbers.add(11);
primeNumbers.add(3);
primeNumbers.add(5);
println(primeNumbers);
08/11/2011
[2, 3 x 2, 5, 7, 11]
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
55
56. Collection Utilities
Multiset
Multiset<Integer> primeNumbers = HashMultiset.create();
primeNumbers.add(2);
primeNumbers.add(3);
primeNumbers.add(7);
primeNumbers.add(11);
primeNumbers.add(3);
primeNumbers.add(5);
println(primeNumbers);
println(premiers.count(3))
08/11/2011
[2, 3 x 2, 5, 7, 11]
2
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
56
57. Joiner / Splitter
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
57
58. Joiner / Splitter
Joiner
List<String> dogs = newArrayList("Milou", "Idefix", "Rintintin");
String names = Joiner.on(", ").join(dogs);
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
58
59. Joiner / Splitter
Joiner
List<String> dogs = newArrayList("Milou", "Idefix", "Rintintin");
String names = Joiner.on(", ").join(dogs);
List<String> dogs = newArrayList("Milou", "Idefix", null, "Rintintin");
String names = Joiner.on(", ").join(dogs);
NullPointerException
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
59
60. Joiner / Splitter
Joiner
List<String> dogs = newArrayList("Milou", "Idefix", "Rintintin");
String names = Joiner.on(", ").join(dogs);
List<String> dogs = newArrayList("Milou", "Idefix", null, "Rintintin");
String names = Joiner.on(", ").join(dogs);
NullPointerException
List<String> dogs = newArrayList("Milou", "Idefix", null, "Rintintin");
String names = Joiner.on(", ").skipNulls().join(dogs);
Milou, Idefix, Rintintin
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
60
61. Joiner / Splitter
Joiner
List<String> dogs = newArrayList("Milou", "Idefix", "Rintintin");
String names = Joiner.on(", ").join(dogs);
List<String> dogs = newArrayList("Milou", "Idefix", null, "Rintintin");
String names = Joiner.on(", ").join(dogs);
NullPointerException
List<String> dogs = newArrayList("Milou", "Idefix", null, "Rintintin");
String names = Joiner.on(", ").skipNulls().join(dogs);
Milou, Idefix, Rintintin
List<String> dogs = newArrayList("Milou", "Idefix", null, "Rintintin");
String names = Joiner.on(", ").useForNull("Doggie").join(dogs);
Milou, Idefix, Doggie, Rintintin
7
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
61
62. Joiner / Splitter
Splitter
Iterable<String> superDogs = Splitter.on(",")
.split("Lassie, Volt, Milou");
"Lassie"
" Volt"
" Milou"
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
62
63. Joiner / Splitter
Splitter
Iterable<String> superDogs = Splitter.on(",")
.split("Lassie, Volt, Milou");
Iterable<String> superDogs = Splitter.on(",")
.split("Lassie, , Volt, Milou");
"Lassie"
" "
" Volt"
" Milou"
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
63
64. Joiner / Splitter
Splitter
Iterable<String> superDogs = Splitter.on(",")
.split("Lassie, Volt, Milou");
Iterable<String> superDogs = Splitter.on(",")
.split("Lassie, , Volt, Milou");
Iterable<String> superDogs = Splitter.on(",")
.trimResults()
.split("Lassie, , Volt, Milou");
"Lassie"
""
"Volt"
"Milou"
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
64
65. Joiner / Splitter
Splitter
Iterable<String> superDogs = Splitter.on(",")
.split("Lassie, Volt, Milou");
Iterable<String> superDogs = Splitter.on(",")
.split("Lassie, , Volt, Milou");
Iterable<String> superDogs = Splitter.on(",")
.trimResults()
.split("Lassie, , Volt, Milou");
Iterable<String> superDogs = Splitter.on(",")
.trimResults()
.omitEmptyStrings()
.split("Lassie, , Volt, Milou");
"Lassie"
"Volt"
"Milou"
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
65
66. Cache – Memoization
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
66
67. Cache – Memoization
Exemple : service renvoyant la dernière version du JDK
public class JdkService {
@Inject
private JdkWebService jdkWebService;
public JdkVersion getLatestVersion() {
return jdkWebService.checkLatestVersion();
}
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
67
68. Cache – Memoization
Cache manuel
public class JdkService {
@Inject
private JdkWebService jdkWebService;
public synchronized JdkVersion getLatestVersion() {
if (versionCache == null) {
versionCache = jdkWebService.checkLatestVersion();
}
return versionCache;
}
private JdkVersion versionCache = null;
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
68
69. Cache – Memoization
Supplier
public class JdkService {
@Inject
private JdkWebService jdkWebService;
public synchronized JdkVersion getLatestVersion() {
if (versionCache == null) {
versionCache = jdkWebService.checkLatestVersion();
public interface Supplier<T> {
}
return versionCache;
T get();
}
}
private JdkVersion versionCache = null;
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
69
70. Cache – Memoization
Supplier
public class JdkService {
@Inject
private JdkWebService jdkWebService;
public JdkVersion getLatestVersion() {
return versionCache.get();
}
private Supplier<JdkVersion> versionCache =
Suppliers.memoize(
new Supplier<JdkVersion>() {
public JdkVersion get() {
return jdkWebService.checkLatestVersion();
}
}
);
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
70
71. Cache – Memoization
Suppliers.memoize()
public class JdkService {
@Inject
private JdkWebService jdkWebService;
public JdkVersion getLatestVersion() {
return versionCache.get();
}
private Supplier<JdkVersion> versionCache =
Suppliers.memoize(
new Supplier<JdkVersion>() {
public JdkVersion get() {
return jdkWebService.checkLatestVersion();
}
}
);
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
71
72. Cache – Memoization
Suppliers.memoizeWithExpiration()
public class JdkService {
@Inject
private JdkWebService jdkWebService;
public JdkVersion getLatestVersion() {
return versionCache.get();
}
private Supplier<JdkVersion> versionCache =
Suppliers.memoizeWithExpiration(
new Supplier<JdkVersion>() {
public JdkVersion get() {
return jdkWebService.checkLatestVersion();
}
},
365, TimeUnit.DAYS
);
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
72
73. Cache – Key-Value
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
73
74. Cache – Key-Value
Exemple
public class FilmService {
@Inject
private ImdbWebService imdbWebService;
public Film getFilm(Long filmId) {
return imdbWebService.loadFilmInfos(filmId);
}
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
74
75. Cache – Key-Value
Cache – Interface
public interface Cache<K, V> extends Function<K, V> {
V get(K key) throws ExecutionException;
V getUnchecked(K key);
void invalidate(Object key);
void invalidateAll();
long size();
CacheStats stats();
ConcurrentMap<K, V> asMap();
}
void cleanUp();
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
75
76. Cache – Key-Value
CacheBuilder & CacheLoader
public class FilmService {
@Inject
private FilmWebService imdbWebService;
public Film getFilm(Long filmId) {
return filmCache.getUnchecked(filmId);
}
private Cache<Long, Film> filmCache = CacheBuilder.newBuilder()
.build(new CacheLoader<Long, Film>() {
public Film load(Film filmId) {
return imdbWebService.loadFilmInfos(filmId);
}
});
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
76
77. Cache – Key-Value
Customisation du CacheBuilder
public class FilmService {
@Inject
private FilmWebService imdbWebService;
public Film getFilm(Long filmId) {
return filmCache.getUnchecked(filmId);
}
private Cache<Long, Film> filmCache = CacheBuilder.newBuilder()
.maximumSize(2000)
.expireAfterWrite(30, TimeUnit.MINUTES)
.build(new CacheLoader<Long, Film>() {
public Film load(Long filmId) {
return imdbWebService.loadFilmInfos(filmId);
}
});
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
77
79. I/O
Java 5
public static byte[] toByteArray(File file) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
boolean threw = true;
InputStream in = new FileInputStream(file);
try {
byte[] buf = new byte[BUF_SIZE];
while (true) {
int r = in.read(buf);
if (r == -1) break;
out.write(buf, 0, r);
}
threw = false;
} finally {
try {
in.close();
} catch (IOException e) {
if (threw) {
logger.warn("IOException thrown while closing", e);
} else {
throw e;
}
}
}
return out.toByteArray();
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
79
80. I/O
Java 7 – Automatic Resource Management (ARM)
public static byte[] toByteArray(File file) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try (InputStream in = new FileInputStream(file);) {
byte[] buf = new byte[BUF_SIZE];
while (true) {
int r = in.read(buf);
if (r == -1) break;
out.write(buf, 0, r);
}
}
}
return out.toByteArray();
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
80
81. I/O
Guava
public static byte[] toByteArray(File file) throws IOException {
return Files.toByteArray(file) ;
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
81
82. I/O
InputSupplier & OutputSupplier
interface InputSupplier<T> {
interface OutputSupplier<T> {
T getInput() throws IOException;
}
T getOutput() throws IOException;
}
InputSupplier<InputStream>
OutputSupplier<OutputStream>
InputSupplier<Reader>
OutputSupplier<Writer>
try {
InputStream stream = new FileInputStream(file) ;
} catch (IOException ioex) {
throw Throwables.propagate(ioex);
}
InputSupplier<InputStream> stream = Files.newInputStreamSupplier(file);
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
82
83. I/O
ByteStreams
byte[] toByteArray(InputStream)
byte[] toByteArray(InputSupplier<InputStream>)
T readBytes(InputSupplier<InputStream>, ByteProcessor<T>)
void write(byte[], OutputSupplier<OutputStream>)
long copy(InputStream, OutputStream)
long copy(InputSupplier<InputStream>,
OutputSupplier<OutputStream>)
InputSupplier<InputStream> join(InputSupplier<InputStream>...)
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
83
84. I/O
CharStreams
String toString(Readable)
String toString(InputSupplier<Readable & Closeable>)
T readLines(InputSupplier<Readable & Closeable>, LineProcessor<T>)
void write(CharSequence, OutputSupplier<Appendable & Closeable>)
long copy(Readable, Appendable)
long copy(InputSupplier<Readable & Closeable>,
OutputSupplier<Appendable & Closeable>)
InputSupplier<Reader> join(InputSupplier<Reader>...)
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
84
85. I/O
Files
byte[] toByteArray(File)
String toString(File, Charset)
List<String> readLines(File, Charset)
void write(byte[], File)
void write(CharSequence, File to, Charset)
void copy(File from, File to)
void copy(InputSupplier<...>, File)
void copy(File, OutputSupplier<...>)
void move(File, File)
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
85
87. Concurrent
Future
List<Note> getNotes(Film film) {
Note noteImdb = imdbService.getNote(film);
Note noteAllo = allocineService.getNote(film);
return ImmutableList.of(noteImdb, noteAllo);
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
87
88. Concurrent
Future
List<Note> getNotes(Film film) {
Note noteImdb = imdbService.getNote(film);
Note noteAllo = allocineService.getNote(film);
return ImmutableList.of(noteImdb, noteAllo);
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
88
89. Concurrent
Future
List<Note> getNotes(Film film) {
Note noteImdb = imdbService.getNote(film);
Note noteAllo = allocineService.getNote(film);
return ImmutableList.of(noteImdb, noteAllo);
}
List<Note> getNotes(Film film) {
Future<Note> noteImdb = imdbService.getNote(film);
Future<Note> noteAllo = allocineService.getNote(film);
return ImmutableList.of(noteImdb.get(), noteAllo.get());
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
89
90. Concurrent
Future – Obtention
public class ImdbService {
private ImdbWebService imdbWebService;
@Inject
ImdbService(ImdbWebService imdbWs) {
this.imdbWebService = imdbWs;
}
public Note getNote(Film film) {
return imdbWebService.getNote(film);
}
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
90
91. Concurrent
Future – Obtention
public class ImdbService {
private ImdbWebService imdbWebService;
private ExecutorService executor;
@Inject
ImdbService(ImdbWebService imdbWs, ExecutorService executor) {
this.imdbWebService = imdbWs;
this.executor = executor;
}
public Future<Note> getNote(final Film film) {
return executor.submit(new Callable<Note>() {
public Note call() {
return imdbWebService.getNote(film);
}
});
}
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
91
92. Concurrent
ListenableFuture
public interface ListenableFuture<V> extends Future<V> {
void addListener(Runnable listener, Executor executor);
}
ListenableFuture<Result> future = ...
future.addListener(new Runnable() {
public void run() {
logger.debug("Future is done");
}
}, executor);
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
92
93. Concurrent
ListenableFuture – Callbacks
future.addListener(new Runnable() {
public void run() {
try {
Result result = Uninterruptibles.getUninterruptibly(future);
storeInCache(result);
} catch (ExecutionException e) {
reportError(e.getCause());
} catch (RuntimeException e) {
// just in case
}
}
}, executor);
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
93
94. Concurrent
ListenableFuture – Callbacks
future.addListener(new Runnable() {
public void run() {
try {
Result result = Uninterruptibles.getUninterruptibly(future);
storeInCache(result);
} catch (ExecutionException e) {
reportError(e.getCause());
} catch (RuntimeException e) {
// just in case
}
}
}, executor);
Futures.addCallback(future, new FutureCallback<Result>() {
public void onSuccess(Result result) {
storeInCache(result);
}
public void onFailure(Throwable t) {
reportError(t);
}
});
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
94
95. Concurrent
ListenableFuture – Brique élémentaire
public final class Futures {
ListenableFuture<O> transform(ListenableFuture<I>,
Function<I, O>)
ListenableFuture<O> chain(ListenableFuture<I>,
Function<I, ListenableFuture<O>>)
ListenableFuture<List<V>> allAsList(List<ListenableFuture<V>>)
ListenableFuture<List<V>> successfullAsList(List<ListenableFuture<V>>)
// ...
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
95
96. Concurrent
ListenableFuture – Obtention
ListenableFuture<V> future = JdkFutureAdapters.listenInPoolThread(f);
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
96
97. Concurrent
ListenableFuture – Obtention
ListenableFuture<V> future = JdkFutureAdapters.listenInPoolThread(f);
Peu performant, car bloque un Thread qui va « attendre » que le Future se
termine pour appeler les listeners.
Mieux vaut créer des ListenableFuture directement, au lieu de simples Future.
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
97
98. Concurrent
ListenableFuture – Obtention
ListenableFuture<V> future = JdkFutureAdapters.listenInPoolThread(f);
public class ImdbService {
private ImdbWebService imdbWebService;
private ListeningExecutorService executor;
@Inject
ImdbService(ImdbWebService imdbWs, ExecutorService executor) {
this.imdbWebService = imdbWs;
this.executor = MoreExecutors.listeningDecorator(executor);
}
public ListenableFuture<Note> getNote(final Film film) {
return executor.submit(new Callable<Note>() {
public Note call() {
return imdbWebService.getNote(film);
}
});
}
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
98
99. Concurrent
ListenableFuture – Quand ?
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
99
100. Concurrent
ListenableFuture – Quand ?
Toujours.
●
Nécessaire pour la plupart des méthodes utilitaires de Futures
●
Évite de devoir changer l'API plus tard
●
Permet aux clients de vos services de faire de la programmation asynchrone
●
Coût en performance négligeable
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
100
101. Concurrent
ListenableFuture – Exemple
ListenableFuture<List<Note>> getNotes(Film film) {
ListenableFuture<Note> noteImdb = imdbService.getNote(film);
ListenableFuture<Note> noteAllo = allocineService.getNote(film);
return Futures.allAsList(noteImdb, noteAllo);
}
On retourne un Future au lieu de bloquer pour renvoyer une List<Note>.
Permet au client de getNotes() d'exécuter d'autres actions en parallèle.
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
101
102. Conclusion
Effective Guava
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
102
103. Bibliographie / liens
Guava
–
http://code.google.com/p/guava-libraries/
Tuto Google-Collections (dvp)
–
http://thierry-lerichedessirier.developpez.com/tutoriels/java/tutogoogle-collections/
Comparaison d’API Java de programmation
fonctionnelle (Xebia)
–
http://blog.xebia.fr/2011/06/29/comparaison-dapijava-de-programmation-fonctionnelle/
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
103
104. Bibliographie / liens
Guava: faire du fonctionnel (Touilleur)
–
http://www.touilleur-express.fr/2010/11/03/googleguava-faire-du-fonctionnel/
Chez Thierry
–
http://www.thierryler.com/
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
104
105. Questions /
Réponses
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
107. Merci de
votre
attention!
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
109. Functional Programming
Filtre en chaine avec FluentIterable ?
Predicate malePredicate = new Predicate<Dog>() {
public boolean apply(Dog dog) {
return dog.getSex() == MALE;
}};
Milou
Idefix
Rintintin
Medor
Predicate eLetterPredicate = new Predicate<Dog>() {
public boolean apply(Dog dog) {
return dog.getName().contains("e");
}};
Idefix
Lassie
Medor
FluentIterable.with(dogs)
.filter(malePredicate)
.filter(eLetterPredicate)
Guava 11-12 ?
08/11/2011
Guava by Google
Idefix
Medor
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
109
110. Functional Programming
Ensembles...
Set<Dog> dogSet = newHashSet(dogs);
Milou
Idefix
Lassie
Rintintin
Lady
Medor
Set<Dog> superDogSet = newTreeSet(superDogs);
Milou
Lassie
Volt
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
110
112. Partition / limit
Avec 4 chiens
import static com.google.common.collect.Lists.partition;
List<List<Dog>> partitions = partition(dogs, 4);
Milou
Idefix
Lassie
Rintintin
Laidy
Medor
import static com.google.common.collect.Iterables.limit;
List<Dog> subList = newArrayList(limit(dogs, 4));
Milou
Idefix
Lassie
Rintintin
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
112
113. Ordering
Classement des chiens
dogs = newArrayList(
new Dog("Milou",
new Dog("Idefix",
new Dog("Lassie",
new Dog("Rintintin",
new Dog("Lady",
new Dog("Medor",
08/11/2011
MALE,
MALE,
FEMALE,
MALE,
FEMALE,
MALE,
6.0),
4.8),
23.5),
12.4),
7.8),
26.2));
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
113
114. Ordering
Classement des chiens
dogs = newArrayList(
new Dog("Milou",
new Dog("Idefix",
new Dog("Lassie",
new Dog("Rintintin",
new Dog("Lady",
new Dog("Medor",
MALE,
MALE,
FEMALE,
MALE,
FEMALE,
MALE,
6.0),
4.8),
23.5),
12.4),
7.8),
26.2));
Ordering<Dog> weightOrdering = new Ordering<Dog>() {
public int compare(Dog left, Dog right) {
return left.getWeight().compareTo(right.getWeight());
}};
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
114
115. Ordering
Classement des chiens
dogs = newArrayList(
new Dog("Milou",
new Dog("Idefix",
new Dog("Lassie",
new Dog("Rintintin",
new Dog("Lady",
new Dog("Medor",
MALE,
MALE,
FEMALE,
MALE,
FEMALE,
MALE,
6.0),
4.8),
23.5),
12.4),
7.8),
26.2));
Ordering<Dog> weightOrdering = new Ordering<Dog>() {
public int compare(Dog left, Dog right) {
return left.getWeight().compareTo(right.getWeight());
}};
List<Dog> orderedDogs = weightOrdering
.nullsLast()
.sortedCopy(dogs);
08/11/2011
Guava by Google
Idefix
Milou
Lady
Rintintin
Lassie
Medor
(4.8)
(6.0)
(7.8)
(12.4)
(23.5)
(26.2)
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
115
116. Ordering
Classement des chiens
Ordering<Dog> weightOrdering = new Ordering<Dog>() {
public int compare(Dog left, Dog right) {
return left.getWeight().compareTo(right.getWeight());
}
}
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
116
117. Ordering
Classement des chiens
Ordering<Dog> weightOrdering = new Ordering<Dog>() {
public int compare(Dog left, Dog right) {
return left.getWeight().compareTo(right.getWeight());
}
}
Dog biggestDog = weightOrdering.max(dogs);
Medor
Dog smallestDog = weightOrdering.min(dogs);
Idefix
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
117
118. Immutables
Map
public static final ImmutableMap<String, Integer> AGES
= ImmutableMap.of("Jean", 32,
"Paul", 12,
"Lucie", 37,
"Marie", 17);
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
118
119. Immutables
Map
public static final ImmutableMap<String, Integer> AGES
= ImmutableMap.of("Jean", 32,
"Paul", 12,
"Lucie", 37,
"Marie", 17);
public static final ImmutableMap<String, Integer> AGES
= new ImmutableMap.Builder<String, Integer>()
.put("Jean", 32)
.put("Paul", 12)
.put("Lucie", 37)
.put("Marie", 17)
.put("Bernard", 17)
.put("Toto", 17)
.put("Loulou", 17)
.build();
08/11/2011
Guava by Google
www.parisjug.org
Copyright © 2008 ParisJug. Licence CC – Creative Commons 2.0 France – Paternité – Pas d'Utilisation Commerciale – Partage des Conditions Initiales à l'Identique
119
Notes de l'éditeur Thierry :
* 35 ans
* 12 ans d’expérience
* Consultant freelance (ICAUDA)
- Assurance
- Grande distribution
* Professeur de Génie Logiciel à l'ESIEA
* Rédacteur pour developpez.com
Etienne :
* 25 ans
* Sfeirien
* Ingénieur généraliste, consultant Java depuis 2008
- Comptabilité
- Édition
- E-commerce
* Utilise Google Collections / Guava depuis 3 ans
THIERRY
Dans cette présentation, on ne peut pas parler de tout ce que contient Guava. On a fait le choix de ne présenter que des aspects simples mais qui nous semblent importants. Ces points sont ceux qui donnent envie d'en savoir plus.
Open Source - Licence Apache 2.0
THIERRY
Effective Java, Item 1 : « Consider static factory methods instead of constructors»
Premier contact avec guava, on commence par un truc bien pratique, même si ce n'est pas révolutionnaire .
La plupart d'entre nous n'aurons pas accès à Java 7 avant 2 ou 3 ans sur les projets de leur entreprise. Je travaille moi-même encore sur des projets en java 1.4 et même en 1.2
Les static factories sont recommandées dans effective Java. D’ailleurs Guava est très inspiré par le contenu de ce livre.
Avec les imports statiques de :
* Lists.newArrayList
* Sets.newTreeSet
* Maps.newHashMap
Le Dog est un peu le fil conducteur de cette présentation.
Varargs
THIERRY
Si on utilise souvent ce Predicate, on peut le définir avec une variable et pas forcément en param
In, and, or, etc. sont dans Predicates
Ici j'ai besoin d'introduire un objet Chien pour la suite.
C'est assez courant de devoir convertir des Objets sur un projet. Disons par exemple que le projet en cours utilise encore des objet en francais et ne s'est pas encore mis à la nouvelle norme de la société.
Il faut bien comprendre qu'on travaille avec des vues. La transformation est faite de façon lazy.
L'appel à size ou à isempty ne déclenche pas le transform.
Par contre elle sera faite à chaque fois qu'on va itérer sur la liste.
Du coup, si on pense qu'on utilisera plus d'une fois la liste, il vaut mieux directement convertir la vue en une vraie liste.
Ca se marie relativement bien avec les Converters de Spring
Guava n'aime pas les null et renvoie une exception si aucun élément n'est trouvé
THIERRY
Il ne faut pas se demander si une collection doit etre immutable mais plutôt si elle a besoin d’être mutable. Et en général, la réponse est non : elle n'a pas besoin d’être mutable, donc autant utiliser une immutable.
Les Immutable ont notamment un interet du point de vue de la concurrence, ce que va expliquer Etienne plus tard
Etienne : Je ne vais pas vraiment l'expliquer. Je vais juste dire en deux phrases que Guava est particulièrement adapté à la programmation concurrente, en particulier grâce à ses collections immutables. Mais je ne rentre pas ds les détails.
C'est super complexe comme écriture. On a tous déjà pondu au moins une fois ce genre de chose, voire pire.
Ici les gens oublient souvent le « final »...
Penser à dire que la vue n'est pas modifiable, mais le set d'origine, si.
Ici je ne déclare pas la constante sous forme de Set mais comme un ImmutableSet pour bien faire passer le message.
« constante » → « variable »
ETIENNE
Je vais maintenant vous présenter les classes qui sont à mon avis les plus utiles dans le package Guava Base.
Ce package contient un grand nombre de classes et méthodes utilitaires « basiques ». On peut considérer qu'il étend en quelque sorte « java.lang ».
Commençons par la classe Objects, qui simplifie beaucoup l'écriture des méthodes classiques d'Object.
Pour cela, on va reprendre pour exemple notre chien, un bean avec 3 champs.
Lorsque les champs peuvent être null, la méthode equals() devient vite verbeuse...
Objects.equal() permet de faire un test d'égalité qui gère les objets nulls, ce qui simplifie beaucoup le code.
De même pour la méthode hashCode(), qui peut être implémentée en une ligne grâce à Objects.hashCode.
Objects.toStringHelper() simplifie l'écriture de la méthode toString(), grâce au builder pattern.
Le code est aussi beaucoup plus lisible.
Pour finir, la méthode compareTo() peut être simplifiée grâce à ComparisonChain.
Le builder pattern nous permet d'enchaîner des comparaisons très simplement..
Il est possible de customiser chaque comparaison de ComparisonChain en passant un comparateur.
C'est notamment utile pour comparer des objects nulls, en utilisant un comparateur qui classe ces derniers à la fin plutôt que de jetter une NPE...
ETIENNE
Passons maintenant à la classe Preconditions, l'une de mes classes préférées, qui permet de valider les arguments des méthodes et constructeurs..
Je vais prendre pour exemple une classe Money, associant un montant et une devise. C'est une classe que l'on retrouve dans de nombreux projets.
Une bonne pratique est de rendre immutables les value objects de ce genre. Cela permet d'éviter les copies défensives, de simplifier la programmation concurrente, et de préserver les invariants une fois l'objet construit.
On voudrait valider les arguments de son constructeur, pour s'assurer qu'elle est correctement construite.
On va donc vérifier que le montant et la devise ne sont pas nulls, et vérifier que le montant est positif.
En Java classique, c'est assez verbeux.
La classe Preconditions permet de simplifier ces checks, grâce à checkNotNull, qui lance une NPE si l'argument est null, et checkArgument, qui lance une IllegalArgumentException si une condition est fausse.
Notez que l'on peut paramétrer les messages d'erreur.
Le code est plus court et plus lisible.
Mais on peut encore simplifier.
Les designers de Guava ont été astucieux, car checkNotNull() retourne son argument après validation. Cela permet de valider un argument avec checkNotNull et de l'assigner à un champ, en une seule ligne.
C'est une fonctionnalité que j'utilise tout le temps.
ETIENNE
Je vais maintenant vous présenter la classe CharMatcher, qui est très utile pour manipuler les chaînes de caractères.
Google avait à l'origine une classe StringUtils, contenant de nombreuses méthodes utilitaires pour manipuler les chaînes de caractères.
Ils avaient par exemple différentes version de la méthode remove(). La première, remove(), supprimait des caractères précis d'une chaîne. La seconde, removeDigits(), supprimait tous les nombres. La troisième, removeWhitespace(), enlevait les espaces blancs.
Les méthodes se multipliant, ils ont réalisé qu'elles représentaient en réalité un produit croisé de deux notions :
(a) qu'est-ce qu'un caractère qui « matche »
(b) que faire de ces caractères
Cette approche n'étant pas scalable, ils ont créé CharMatcher.
Une instance de CharMatcher correspond à la première notion, et les opérations que l'on invoque sur ce CharMatcher correspondent à la seconde.
On peut obtenir un CharMatcher de différentes manières.
La première consiste à utiliser l'une des constantes disponibles.
THIERRY
* Multimap
* BiMap
* MultiSet
THIERRY
Une Multimap, c'est grossomodo une « Map de List »
THIERRY
Pour faire une Bimap en java pur, il faut en gros faire deux map symétriques
THIERRY
List : Ordre + Doublon
Set : Sans ordre significatif + Sans Doublon
MultiSet : Sans ordre significatif + Doublon
THIERRY
C'est le genre de fonction qu'on a tous eut à écrire un jour ou l'autre.
Le splitter est grosso modo l'inverse du joiner.
ETIENNE
Je vais maintenant vous présenter deux types de caches disponibles dans Guava :
- la mémoization d'une part, qui permet de cacher le résultat unique d'un appel à une fonction
- les caches « classiques » d'autre part, qui permettent de cacher des couples clé-valeur, comme dans une Map
Prenons pour exemple un service permettant d'obtenir des informations sur la dernière version du JDK disponible.
Pour ce faire, ce service appelle un web-service, ce qui est lent et gourmand en ressources.
On voudrait donc cacher son résultat.
Une première approche consiste à faire de la mémoization « manuelle », en cachant le résultat dans un champ.
Cela nécessite cependant de synchroniser la méthode, ce qui peut poser des problèmes de contention.
On pourrait éviter la synchronisation, en mettant en place un double-checked locking, mais le code est complexe, verbeux, et souvent mal implémenté.
Guava permet de mémoizer une valeur très simplement, grâce à l'interface Supplier.
Un Supplier est une classe qui peut fournir des objets d'un certain type, une Factory en quelque sorte.
Pour mémoizer notre appel, on créé un Supplier, qui va appeller notre web-service lorsque l'on invoque sa méthode « get ».
On combine ce Supplier avec la méthode utilitaire Suppliers.memoize(). Elle renvoie un nouveau Supplier, qui décore le premier, et cache le résultat du premier appel.
L'avantage, c'est que les problématiques de synchronization sont gérées par Guava, avec une variante du double-checked locking.
Problème : nous cachons la version du JDK éternellement... Or, il arrive -certes rarement- qu'une nouvelle version soit disponible.
Pas de problème, Guava propose une seconde méthode, Suppliers.memoizeWithExpiration(), qui permet de mémoizer le résultat pour une durée déterminée.
Dans notre exemple, un an me semble raisonnable ;)
ETIENNE
Nous allons maintenant voir comment mettre en place un cache clé-valeur.
Prenons pour exemple un service permettant de récupérer des informations sur un film, en appelant IMDB, l'Internet Movie DataBase, via un web service.
On voudrait cacher les appels à ce service.
Contrairement à l'exemple précédent, le service peut renvoyer des résultats différents selon l'ID du film passé en paramètre.
Guava 10 a introduit un nouveau package dédié aux caches, com.google.common.cache. Il contient une interface pour représenter un cache, avec des méthodes pour charger et invalider des valeurs, obtenir des statistiques d'utilisation, et obtenir une vue du cache sous la forme d'une Map.
Introduisons le cache Guava dans notre exemple.
Pour le construire, il est recommandé d'utiliser CacheBuilder, qui permet de configurer simplement un cache via une interface fluide.
On passe à notre builder un CacheLoader, l'interface à implémenter pour indiquer à Guava comment charger les nouvelles valeurs.
Il nous suffit maintenant d'appeler filmCache.getUnchecked() dans la méthode getFilm(). Le cache se charge du reste.
Problème : nous voulons expirer les éléments régulièrement, et limiter la taille totale du cache, qui utilise trop de mémoire.
Nous pouvons configurer ces propriétés via l'interface fluide de CacheBuilder:
- taille maximum de 2000 éléments
- expiration des éléments après 30 minutes
CacheBuilder est un excellent exemple d'une API très simplequi cache (;)) des fonctionnalités puissantes et complexes.
ETIENNE
Le package common.io contient des classes et méthodes utilitaires pour travailler avec Java I/O, c'est-à-dire les input streams, output streams, readers, writers, et fichiers.
La gestion des entrées/sorties est très verbeuse en Java. Il faut fermer correctement les ressources, et gérer les IOExceptions pouvant être lancé lors de l'ouverture, l'utilisation, ou la fermeture de ces dernières.
La bonne pratique est de fermer les ressources dans des blocs finally, comme dans cet exemple. Si une exception est lancée lors de l'utilisation de la ressource, il faut veiller à ne pas l'« avaler » en jettant une nouvelle exception dans le bloc finally.
http://www.ibm.com/developerworks/java/library/j-jtp03216/index.html
Java 7 simplifie la gestion des ressources, avec les interfaces AutoCloseable, et le méchanisme de multi-exceptions (todo).
Mais nombre d'entreprises sont timides (?) à l'adoption de Java 7 (?). Et Guava I/O a plus d'un tour dans son sac...
Voici l'équivalent Guava du code précédent.
Guava I/O est basé sur la notion d'IntputSupplier et d'OutputSupplier. Ces deux interfaces représentent des fabriques d'objets I/O, encapsulant la création d'InputStream, OutputStream, Reader, et Writer.
La construction de ces ressources peut souvent lancer des IOExceptions. En utilisant ces suppliers, on laisse Guava se charger du cycle de vie des ressources (ouverture, fermeture, gestion des exceptions).
Cette approche est aussi très modulaire. Elle permet par exemple à Google d'avoir des suppliers basés sur GFS, le file-system interne de Google.
Les méthodes utilitaires de Guava I/O sont réparties dans 3 classes. ByteStreams permet de manipuler des bytes.
CharStreams contient des méthodes équivalentes, mais fonctionnant avec des caractères, càd en terme de Reader, Writer, CharSequence, et String.
Enfin, Files, se base sur ByteStreams et CharStreams pour faciliter la manipulation de fichiers
ETIENNE
Introduire brièvement util.concurrent en disant que Guava est tout particulièrement indiqué pour la programmation concurrente, car privilégiant l'immutabilité (collections immutables, mais aussi nombre autre classes telles que CharMatcher / Joiner / Splitter)
ListenableFuture est un Future avec une méthode supplémentaire, qui permet d'ajouter des listeners. Ils sont appelés lorsque le Future est terminé, qu'il s'agisse d'un succès, d'une exception, ou d'une annulation. Si le Future est déjà terminé lorsque l'on appelle addListener(), le listener est appelé immédiatement.
Cela permet de faire de la programmation asynchrone,
ETIENNE ou THIERRY
Déjà possible avec les Functionnal-Collections
THIERRY
Ici j'utilise des Set à la place des listes
THIERRY
Attention : ne pas oublier equals et hashCode
THIERRY
Petit bonus du genre de fonctionnalité qu'on est tout le temps obligés de faire.
THIERRY
THIERRY
THIERRY
THIERRY
THIERRY
THIERRY
THIERRY