soirée guava et lombok avec thierry leriche
DESCRIPTION
Guava est une librairie open source créée et maintenue par les équipes de Google. Inspirée des outils internes du géant, Guava propose de nombreux mécanismes (prog fonctionnelle) pour manipuler les collections, créer des caches customisés, faciliter la gestion de la concurrence et les IOs. De son coté, Lombok est également un projet Open Source. Lombok et Lombok-pg simplifient sensiblement l’écriture de code classique (builders, delegates, etc.) et des nombreuses méthodes purement techniques et indispensables (getters, setters, hashCode, equals, etc.) qui polluent nos objets. Durant cette présentation, après un rapide constat de la verbosité de nos beans, nous feront un tour d’horizon de Lombok et Guava. Nous verrons comment ils nous aident à écrire du code concis et de qualité.TRANSCRIPT
![Page 1: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/1.jpg)
Milou fait un régimeGuava - Lombok
NORMANDY JUG
![Page 2: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/2.jpg)
SPONSORS
NORMANDY JUG
![Page 3: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/3.jpg)
Thierry Leriche-Dessirier
icauda.com
Consultant JEE freelance Professeur de Génie Logiciel à l’ESIEA Rédacteur pour Programmez Rédacteur pour Developpez.com
@thierryleriche
![Page 4: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/4.jpg)
Cours
FAQ
Interviews
Articles / tutoriels
Magazine
Forums
News
Agendas
Critiques
![Page 5: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/5.jpg)
13 OOO OOO pages vues par mois
5 500 000 visites par mois
2 500 000 visites uniques par mois
5 000 messages forum par jour
![Page 6: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/6.jpg)
Agen
da
Milou est trop lourd (intro)
Lombok (et Lombok-pg) en action
Tour d’horizon de Guava
![Page 7: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/7.jpg)
Milou est trop lourd (et doit faire un régime)
I am Milou
![Page 8: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/8.jpg)
public class Dog {
private Integer id ; private String name ; private String fullName ; private SexeEnum sex ; private Date birthday ; private String race ; private Boolean lof ; private Double weight ; private Double size ; private List<String> colors ;
...
DO
G 5
![Page 9: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/9.jpg)
id name fullName sex birthday race lof weight size Colors
Constructeurs Getters / setters toString () equals () hashCode () compareTo ()
![Page 10: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/10.jpg)
clic clicdémo
id name fullName sex birthday race lof weight size Colors
Constructeurs Getters / setters toString () equals () hashCode () compareTo ()
![Page 11: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/11.jpg)
public class Dog implements Comparable<Dog> {
...
@Override public int compareTo(Dog other) { int result = 0;
result = name.compareTo(other.name); if (result != 0) { return result; }
... }
Code très limite… NPE ?...
![Page 12: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/12.jpg)
id name fullName sex birthday race lof weight size Colors
Constructeurs Getters / setters toString () equals () hashCode () compareTo ()
210 lignes10 attributs
![Page 13: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/13.jpg)
210 lignes de code
10 attributs
Java
![Page 14: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/14.jpg)
Va c
herc
her G
uava
toString () equals () hashCode () compareTo ()
Commons FAQ 1-2
![Page 15: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/15.jpg)
Base
Objects
![Page 16: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/16.jpg)
public String toString() { return "Dog [id=" + id + ", name=" + name + ", fullName=" + fullName + ", sex=" + sex + ", birthday=" + birthday + ", race=" + race + ", lof=" + lof + ", weight=" + weight + ", size=" + size + ", colors=" + colors + "]";}
Java
5 5
toString ()
Simple, efficace et bien pourri
![Page 17: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/17.jpg)
public String toString() { StringBuilder sb = new StringBuilder();
sb.append(Dog.class.getSimpleName()) .append("[id=").append(id) .append(", name=").append(name) .append(", fullName=").append(fullName) ... .append(", colors=").append(colors);
return sb.toString();}
Java
5 5
toString ()
Mieux mais sans plus
![Page 18: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/18.jpg)
public String toString() { return Objects.toStringHelper(this) .add("id", id) .add("name", name) .add("fullName", fullName) ... .add("colors", colors) .toString();}
Gua
va G
toString ()
Builder
![Page 19: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/19.jpg)
public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false;
Dog other = (Dog) obj; if (birthday == null) { if (other.birthday != null) return false; } else if (!birthday.equals(other.birthday)) return false; if (fullName == null) { if (other.fullName != null) return false; ... } else if (!race.equals(other.race)) return false; if (sex != other.sex) return false;
return true;}
Java
5 5
equals ()
birthday, fullname, name, race et sex
Carrément illisible
![Page 20: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/20.jpg)
public boolean equals(Object obj) { if (!(obj instanceof Dog)) return false;
Dog other = (Dog) obj;
return Objects.equal(birthday, other.birthday) && Objects.equal(fullname, other.fullname) && Objects.equal(name, other.name) && Objects.equal(race, other.race) && sex == other.sex;}
Gua
va G
equals ()
birthday, fullname, name, race et sex
![Page 21: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/21.jpg)
public int hashCode() { final int prime = 31; int result = 1;
result = prime * result + ((birthday == null) ? 0 : birthday.hashCode()); result = prime * result + ((fullName == null) ? 0 : fullName.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((race == null) ? 0 : race.hashCode()); result = prime * result + ((sex == null) ? 0 : sex.hashCode());
return result;}
Java
5 5
hashCode ()
birthday, fullname, name, race et sex
![Page 22: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/22.jpg)
public int hashCode() {
return Objects.hashCode(birthday, fullName, name, race, sex);}
Gua
va G
hasCode()
birthday, fullname, name, race et sex
![Page 23: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/23.jpg)
public int compareTo(Dog other) { int result = 0;
result = name.compareTo(other.name); if (result != 0) { return result; } result = fullname.compareTo(other.fullname); if (result != 0) { return result; }
...}
Java
5 5
compareTo ()
name, fullname, birthday, weight, size, race et sex
![Page 24: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/24.jpg)
name.compareTo(other.name)
compareTo ()
other.name.compareTo(name)Vs
![Page 25: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/25.jpg)
public int compareTo(Dog other) { return ComparisonChain.start() .compare(name, other.name) .compare(fullName, other.fullName) .compare(birthday, other.birthday) .compare(weight, other.weight) .compare(size, other.size) .compare(race, other.race) .compare(sex, other.sex) .result();}
Gua
va G
compareTo ()
name, fullname, birthday, weight, size, race et sex
![Page 26: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/26.jpg)
Lom
bok
en action
![Page 27: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/27.jpg)
Régime
Annotations de base
![Page 28: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/28.jpg)
@NoArgsConstructor / @RequiredArgsConstructor / @AllArgsConstructor constructeurs
@Getter / @Setter @ToString @EqualsAndHashCode @Data @Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor
Régi
me
![Page 29: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/29.jpg)
clic clicdémo
Régi
me @NoArgsConstructor /
@RequiredArgsConstructor / @AllArgsConstructor
@Getter / @Setter @ToString @EqualsAndHashCode @Data
![Page 30: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/30.jpg)
210 lignes de code
10 attributs
Java
12 lignes + 2-3 @ + compareTo()Lombok
![Page 31: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/31.jpg)
name, sex
@RequiredArgsConstructor(staticName = "of")public class Dog {
private Integer id; @NonNull private String name; private String fullName; @NonNull private SexeEnum sex; private Date birthday; ...
Dog dog = Dog.of("Milou", MALE);
Fact
ory L
![Page 32: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/32.jpg)
name, sex
private Dog(@NonNull final String name, @NonNull final SexeEnum sex) { if (name == null) throw new NullPointerException("name"); if (sex == null) throw new NullPointerException("sex");
this.name = name; this.sex = sex;}
public static Dog of(@NonNull final String name, @NonNull final SexeEnum sex) { return new Dog(name, sex);}
@RequiredArgsConstructor(staticName = "of")public class Dog {
private Integer id; @NonNull private String name; private String fullName; @NonNull private SexeEnum sex; private Date birthday; ...
Dog dog = Dog.of("Milou", MALE);
Fact
ory L
![Page 33: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/33.jpg)
Trucs pratiques
Se simplifier la vie
![Page 34: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/34.jpg)
@Cleanup @Synchronized @SneakyThrows @Log @Delegate
valPrati
que
![Page 35: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/35.jpg)
public void lireJava6(String from) { InputStream in = null; try { in = new FileInputStream(from); byte[] b = new byte[10000]; while (true) { int r = in.read(b); if (r == -1) break; ... } } catch (Exception e) { ... } finally { if (in != null) { try { in.close(); } catch (Exception e) { ... } } ...
Ress
ourc
es 5
![Page 36: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/36.jpg)
public void lire(String from) throws IOException {
@Cleanup InputStream in = new FileInputStream(from);
byte[] b = new byte[10000]; while (true) { int r = in.read(b); if (r == -1) break; ... }}Re
ssou
rces L
![Page 37: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/37.jpg)
Délombok
Revenir sans la lib
![Page 38: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/38.jpg)
Dél
ombo
k <properties> <lombok.sourceDirectory> ${project.basedir}/src/main/java </lombok.sourceDirectory>...
<build> <groupId>org.projectlombok</groupId> <artifactId>maven-lombok-plugin</artifactId> <executions> <execution> <phase>generate-sources</phase> </execution> </executions> ...
mvn lombok:delombok
java -jar lombok.jar delombok src -d src-delomboked
XML
![Page 39: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/39.jpg)
Dél
ombo
k @Datapublic class Dog { private Integer id; private String name; private String fullName; private SexeEnum sex; private Date birthday; private String race; private Boolean lof; private Double weight; private Double size; private List<String> colors;}
5public class Dog { private Integer id; private String name; private String fullName; ... private List<String> colors;
public DogLombok() { }
@java.lang.Override @java.lang.SuppressWarnings("all") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != this.getClass()) return false; final Dog other = (Dog)o; if (this.getId() == null ? other.getId() != null : !this.getId().equals(other.getId())) return false; ...
@java.lang.Override @java.lang.SuppressWarnings("all") public int hashCode() { final int PRIME = 31; int result = 1; result = result * PRIME + (this.getId() == null ? 0 : this.getId().hashCode()); result = result * PRIME + (this.getName() == null ? 0 : this.getName().hashCode());
mvn lombok:delombok
5
![Page 40: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/40.jpg)
Lombok-pg
Annotations supplémentaires
![Page 41: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/41.jpg)
@Action @Function @EnumId @Rethrow / @Rethrows @Singleton @AutoGenMethodStub @BoundPropertySupport / @BoundSetter @DoPrivileged @ExtensionMethod @ListenerSupport @WriteLock / @ReadLock @Await / @Signal / @AwaitBeforeAndSignalAfter @Sanitize.Normalize / .With @SwingInvokeLater / @SwingInvokeAndWait @Validate.NotEmpty / .NotNull / .With @VisibleForTesting
Anno
tatio
ns P
g @Builder @LazyGetter @FluentSetter @Predicate
![Page 42: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/42.jpg)
@FluentSetter@Getterpublic class Dog {
private Integer id ; private String name ; private String fullName ;
...
DogLombok dog = new DogLombok();dog.name("Milou").sex(MALE);
Flue
nt
println( dog.getName()); // Milouprintln( dog.getSex()); // MALE
L
![Page 43: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/43.jpg)
@Builder@Getterpublic class Dog {
private Integer id ; private String name ; private String fullName ;
...
Dog dog = Dog.dog().name("Milou").sex(MALE).build();
Build
er
println( dog.getName()); // Milouprintln( dog.getSex()); // MALE
L
![Page 44: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/44.jpg)
@ExtensionMethod({ Dog.class, MyDogExtensionClass.class })public class DogWithExtension {
public void foo() { Dog milou = new Dog("Milou", 12.5, ...); boolean isTooFat = milou.isTooFat(); }}
class MyDogExtensionClass {
public static boolean isTooFat(final Dog dog) { double imc = dog.getWeight() / pow(dog.getSize(), 2); return 25 < imc; }}
exte
nsio
n L
Avec paramètres FAQ 9
http://blog.developpez.com/todaystip/p11165/dev/java/extensionmethod-de-lombok-pg/
![Page 45: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/45.jpg)
Lombok or not Lombok ?
Avantages et inconvénients
![Page 46: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/46.jpg)
Pro
/ Co
ns Byte code modifié Version en 0.x Documentation des prog ? Magique ?
Compacité Lecture simplifiée Code normée Délombok (pour essayer)
![Page 47: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/47.jpg)
Gua
va
tour d’horizon
![Page 48: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/48.jpg)
Factory Methods
Les choses que j’aime
![Page 49: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/49.jpg)
List<Integer> primeNumbers = new ArrayList<Integer>();
Set<String> colors = new TreeSet<String>();
Map<String, Integer> ages = new HashMap<String, Integer>();Java
5 5< new Vs static factories >
![Page 50: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/50.jpg)
Java
5
Map<String, List<String>> trucs = new HashMap<String, List<String>>();
Map<? extends Person, Map<String, List<String>>> trucs = new TreeMap<? extends Person, Map<String, List<String>>>();
Map<? extends Wrapper<String, Sex, Person>, Map<String, List<Set<Adress<String, Integer, Country>>>>> trucs = ...
dur d
ur ? 5
List<Integer> primeNumbers = new ArrayList<Integer>();
Set<String> colors = new TreeSet<String>();
Map<String, Integer> ages = new HashMap<String, Integer>();5
< new Vs static factories >
![Page 51: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/51.jpg)
Java
5
List<Integer> primeNumbers = new ArrayList<>();
Set<String> colors = new TreeSet<>();
Map<String, Integer> ages = new HashMap<>();Java
7
Qui utilise Java 7 en prod ?
7
List<Integer> primeNumbers = new ArrayList<Integer>();
Set<String> colors = new TreeSet<String>();
Map<String, Integer> ages = new HashMap<String, Integer>();5
< new Vs static factories >
![Page 52: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/52.jpg)
Java
5Ja
va 7
Qui utilise Java 7 en prod ?
List<Integer> primeNumbers = newArrayList();
Set<String> colors = newTreeSet();
Map<String, Integer> ages = newHashMap();Gua
va
Dès maintenant !
G
List<Integer> primeNumbers = new ArrayList<>();
Set<String> colors = new TreeSet<>();
Map<String, Integer> ages = new HashMap<>();
List<Integer> primeNumbers = new ArrayList<Integer>();
Set<String> colors = new TreeSet<String>();
Map<String, Integer> ages = new HashMap<String, Integer>();57
< new Vs static factories >
![Page 53: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/53.jpg)
Java
5Ja
va 7
Qui utilise Java 7 en prod ?
List<Integer> primeNumbers = newArrayList();
Set<String> colors = newTreeSet();
Map<String, Integer> ages = newHashMap();Gua
va
Dès maintenant !
G
List<Integer> primeNumbers = new ArrayList<>();
Set<String> colors = new TreeSet<>();
Map<String, Integer> ages = new HashMap<>();
List<Integer> primeNumbers = new ArrayList<Integer>();
Set<String> colors = new TreeSet<String>();
Map<String, Integer> ages = new HashMap<String, Integer>();57
var primeNumbers = new ArrayList<Integer>();
-> primeNumbers.size(); ...
Lom
bok
< new Vs static factories >
L
![Page 54: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/54.jpg)
List<Dog> dogs = newArrayList( new Dog("Milou", 12.5, MALE, ...),
new Dog("Rintintin", 45.0, MALE, ...),
new Dog("Volt", 10.3, MALE, ...),
new Dog("Lassie", 45.0, FEMALE, ...),
new Dog("Pluto", 22.0, MALE, ...),
new Dog("Medor", 35.6, MALE, ...));
List
of d
ogs
G
[Milou, Rintintin, Volt, Lassie, Pluto, Medor]
< new Vs static factories >
![Page 55: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/55.jpg)
Immutables
Pour que ça ne change pas
![Page 56: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/56.jpg)
Quand ?immutable
![Page 57: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/57.jpg)
Quand ?immutable
mutable
On se demande souvent si une liste doit être immutable mais c’est prendre le problème dans le mauvais sens. La plupart du temps, ce qu’il faut vraiment se demander, c’est si la liste a besoin d’être mutable.
![Page 58: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/58.jpg)
Java
5 Set<Integer> temp = new LinkedHashSet<Integer>(Arrays.asList(1, 2, 3, 5, 7));
Set<Integer> primes = Collections.unmodifiableSet(temp);
< unmodifiables Vs immutables >
![Page 59: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/59.jpg)
Java
5
Set<Integer> primes = ImmutableSet.of(1, 2, 3, 5, 7);
Set<Integer> temp = new LinkedHashSet<Integer>(Arrays.asList(1, 2, 3, 5, 7));
Set<Integer> primes = Collections.unmodifiableSet(temp);
Gua
va< unmodifiables Vs immutables >
G
![Page 60: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/60.jpg)
Of
ImmutableSet.of(E e1)ImmutableSet.of(E e1, E e2)ImmutableSet.of(E e1, E e2, E e3)ImmutableSet.of(E e1, E e2, E e3, E e4)ImmutableSet.of(E e1, E e2, E e3, E e4, E e5)ImmutableSet.of(E e1, E e2, E e3, E e4, E e5, E e6, E...)
Ne prend pas de null
Of
ImmutableSet.of()
Vide
Map et List FAQ 4
< unmodifiables Vs immutables >
G
http://blog.developpez.com/guava/p10589/collection/title-212/
![Page 61: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/61.jpg)
Java
5 public class Dog { private String name; ... private List<String> colors;
public Dog(String name, List<String> colors) { this.name = name; ... this.colors = Collections.unmodifiableList( new ArrayList<String>(colors)); }
public List<String> getColors() { return colors; }
5< Copie de défense >
![Page 62: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/62.jpg)
Gua
va public class Dog { private String name; ... private ImmutableList<String> colors;
public Dog(String name, List<String> colors) { this.name = name; ... this.colors = ImmutableList.copyOf(colors); }
public ImmutableList<String> getColors() { return colors; }
G
Message clair
< Copie de défense >
![Page 63: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/63.jpg)
Collections en plus
Multimap, Bipap, Multiset, Table
![Page 64: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/64.jpg)
Java
5 Map<String, List<String>> dogFavoriteColors = new HashMap<String, List<String>>(); 5
< Multi Map >
List<String> milouColors = dogFavoriteColors.get("Milou");if(milouColors == null) { milouColors = new ArrayList<String>(); dogFavoriteColors.put("Milou",milouColors);}milouColors.add("Vert");
5
![Page 65: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/65.jpg)
Java
5 Map<String, List<String>> dogFavoriteColors = new HashMap<String, List<String>>(); 5
< Multi Map >
List<String> milouColors = dogFavoriteColors.get("Milou");if(milouColors == null) { milouColors = new ArrayList<String>(); dogFavoriteColors.put("Milou",milouColors);}milouColors.add("Vert");
5G
uava Multimap<String, String> dogFavoriteColors =
HashMultimap.create();
dogFvoriteColors2.put("Milou", "Jaune");dogFavoriteColors2.put("Milou", "Rouge");
G
![Page 66: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/66.jpg)
< Bi Map >
Gua
va BiMap<String, Dog> tatouages = HashBiMap.create();tatouages.put("ABC123", new Dog("Milou") );tatouages.put("MBD324", new Dog("Volt") );tatouages.put("JFT672", new Dog("Lassie") );
ABC123=MilouMDB324=VoltJFT672=LassieIl est possible de changer la valeur associée à une clé mais pas d'avoir deux clés avec la même valeur (IllegalArgumentException).
println( tatouages );
Une map bijective
{ABC123=Milou,MBD324=Volt,JFT672=Lassie}
G
println( tatouages.inverse() );{Milou=ABC123,Volt=MBD324,Lassie=JFT672}
![Page 67: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/67.jpg)
< Multi Set >
Gua
va Multiset<Integer> ages = HashMultiset.create();ages.add(2);ages.add(3);ages.add(7);ages.add(11);ages.add(3);ages.add(5);
println( ages );
println( ages.count(3) )
[2, 3 x 2, 5, 7, 11]
2
G
![Page 68: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/68.jpg)
< Table >
Gua
va // Sexe, couleur, nomTable<SexeEnum, String, String> dogTable = HashBasedTable.create();
dogTable.put(MALE, "jaune", "Pluto");dogTable.put(MALE, "blanc", "Milou");dogTable.put(MALE, "noir", "Medor");dogTable.put(FEMALE, "noir", "Lassie");dogTable.put(FEMALE, "blanc", "Pupuce");
G
![Page 69: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/69.jpg)
< Table >
Gua
va // Sexe, couleur, nomTable<SexeEnum, String, String> dogTable = HashBasedTable.create();
dogTable.put(MALE, "jaune", "Pluto");dogTable.put(MALE, "blanc", "Milou");dogTable.put(MALE, "noir", "Medor");dogTable.put(FEMALE, "noir", "Lassie");dogTable.put(FEMALE, "blanc", "Pupuce");
Map<String, String> maleRow = dogTable.row(MALE);println( maleRow )
{ jaune=Pluto, noir=Medor, blanc=Milou }
G
Map<String, String> femaleRow = dogTable.row(FEMALE);println( femaleRow )
{ noir=Lassie, blanc=Pupuce }
![Page 70: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/70.jpg)
< Table >
Gua
va // Sexe, couleur, nomTable<SexeEnum, String, String> dogTable = HashBasedTable.create();
dogTable.put(MALE, "jaune", "Pluto");dogTable.put(MALE, "blanc", "Milou");dogTable.put(MALE, "noir", "Medor");dogTable.put(FEMALE, "noir", "Lassie");dogTable.put(FEMALE, "blanc", "Pupuce");
Map<SexeEnum, String> blancColumn = dogTable.column("blanc");println( blancColumn )
{ FEMALE=Pupuce, MALE=Milou }
Map<SexeEnum, String> jauneColumn = dogTable.column("jaune");println( jauneColumn )
{ MALE=Pluto }
![Page 71: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/71.jpg)
Base
Préconditions, joiner, splitter, optional
![Page 72: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/72.jpg)
toString () equals () hashCode () compareTo ()
![Page 73: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/73.jpg)
public class Dog {
private Integer id ; private String name ; private String fullName ; ...
public Dog(String name, String fullName, ...) { if(name == null) { throw new NPE("Le nom bla bla"); } if(fullName == null) { throw new NPE("bla bla"); } ...
this.name = name; this.fullName = fullName; ... }
DO
G 5< Preconditions >
![Page 74: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/74.jpg)
import static com.google.common.base.Preconditions.*;
public class Dog {
private Integer id ; private String name ; private String fullName ; ...
public Dog(String name, String fullName, ...) {
this.name = checkNotNull(name, "bla bla"); this.fullName = checkNotNull(fullName, "bla bla"); ... }
DO
G G< Preconditions >
checkNotNull() NPEcheckArgument() IAEcheckState() ISE
![Page 75: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/75.jpg)
Join
er String names = Joiner.on(", ") .join(newArrayList("Lassie", "Volt", "Milou"));
List<String> dogNames = newArrayList("Lassie", "Volt", "Milou");
StringBuilder sb = new StringBuilder();boolean first = true;for (String name : dogNames) { if(name != null || name.trim().isEmpty()) { continue; } if (!first) { sb.append(", "); }
sb.append(name); first = false;}
String names = sb.toString();
Java classique
G"Lassie, Volt, Milou"
![Page 76: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/76.jpg)
Join
er String names = Joiner.on(", ") .join(newArrayList("Lassie", "Volt", "Milou"));
String names = Joiner.on(", ") .join(newArrayList("Lassie", "Volt", null, "Milou"));
NPE
G"Lassie, Volt, Milou"
![Page 77: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/77.jpg)
Join
er String names = Joiner.on(", ") .join(newArrayList("Lassie", "Volt", "Milou"));
String names = Joiner.on(", ") .join(newArrayList("Lassie", "Volt", null, "Milou"));
String names = Joiner.on(", ") .skipNulls() .join(newArrayList("Lassie", "Volt", null, "Milou"));
"Lassie, Volt, Milou"
NPE
G"Lassie, Volt, Milou"
G
![Page 78: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/78.jpg)
Join
er String names = Joiner.on(", ") .join(newArrayList("Lassie", "Volt", "Milou"));
String names = Joiner.on(", ") .join(newArrayList("Lassie", "Volt", null, "Milou"));
String names = Joiner.on(", ") .skipNulls() .join(newArrayList("Lassie", "Volt", null, "Milou"));
"Lassie, Volt, Milou"
NPE
String names = Joiner.on(", ") .useForNull("Anonymous")) .join(newArrayList("Lassie", "Volt", null, "Milou"));
"Lassie, Volt, Anonymous, Milou"
G"Lassie, Volt, Milou"
GG
http://blog.developpez.com/guava/p11054/base/joiner-pour-assembler-des-items/
![Page 79: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/79.jpg)
Splitt
er Iterable<String> dogNames = Splitter.on(",") .split("Lassie, Volt, Milou");
[ "Lassie", "Volt", "Milou" ]
![Page 80: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/80.jpg)
Splitt
er Iterable<String> dogNames = Splitter.on(",") .split("Lassie, Volt, Milou");
[ "Lassie", "Volt", "Milou" ]
Iterable<String> dogNames = Splitter.on(",") .split("Lassie, Volt, ,Milou");
[ "Lassie", "Volt", " ", "Milou" ]
![Page 81: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/81.jpg)
Splitt
er Iterable<String> dogNames = Splitter.on(",") .split("Lassie, Volt, Milou");
[ "Lassie", "Volt", "Milou" ]
Iterable<String> dogNames = Splitter.on(",") .split("Lassie, Volt, ,Milou");
[ "Lassie", "Volt", " ", "Milou" ]
Iterable<String> dogNames = Splitter.on(",") .trimResults() .split("Lassie, Volt, ,Milou");
[ "Lassie", "Volt", "", "Milou" ]
![Page 82: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/82.jpg)
Splitt
er Iterable<String> dogNames = Splitter.on(",") .split("Lassie, Volt, Milou");
[ "Lassie", "Volt", "Milou" ]
Iterable<String> dogNames = Splitter.on(",") .split("Lassie, Volt, ,Milou");
[ "Lassie", "Volt", " ", "Milou" ]
Iterable<String> dogNames = Splitter.on(",") .trimResults() .split("Lassie, Volt, ,Milou");
Iterable<String> dogNames = Splitter.on(",") .trimResults() .omitEmptyStrings() .split("Lassie, Volt, ,Milou");
G[ "Lassie", "Volt", "Milou" ]
http://blog.developpez.com/guava/p11045/annotation/splitter-pour-separer-des-items/
[ "Lassie", "Volt", "", "Milou" ]
![Page 83: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/83.jpg)
Opti
onal
Wrapper Optional <T>
Dog dog = new Dog("Milou", ...);
Optional<Dog> opt = Optional.of(dog);
assertTrue( opt.isPresent() ); assertEquals( "Milou", opt.get().getName() );
![Page 84: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/84.jpg)
Opti
onal
Wrapper Optional <T>
Dog dog = new Dog("Milou", ...);
Optional<Dog> opt = Optional.of(dog);
assertTrue( opt.isPresent() ); assertEquals( "Milou", opt.get().getName() );
Optional<Dog> opt = Optional.absent();assertFalse( opt.isPresent() ); opt.get(); ISE
![Page 85: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/85.jpg)
Opti
onal
Wrapper Optional <T>
Dog dog = new Dog("Milou", ...);
Optional<Dog> opt = Optional.of(dog);
assertTrue( opt.isPresent() ); assertEquals( "Milou", opt.get().getName() );
Optional<Dog> opt = Optional.absent();assertFalse( opt.isPresent() ); opt.get(); ISE
Dog dog = null;Optional<Dog> opt = Optional.of(dog); NPE
Optional<Dog> opt = Optional.fromNullable(dog);
![Page 86: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/86.jpg)
http://blog.developpez.com/guava/p11163/base/le-wrapper-optional-de-guava/
Opti
onal
Wrapper Optional <T>
Dog dog = new Dog("Milou", ...);
Optional<Dog> opt = Optional.of(dog);
assertTrue( opt.isPresent() ); assertEquals( "Milou", opt.get().getName() );
Optional<Dog> opt = Optional.absent();assertFalse( opt.isPresent() ); opt.get(); ISE
Dog dog = null;Optional<Dog> opt = Optional.of(dog); NPE
Optional<Dog> opt = Optional.fromNullable(dog);
Dog dog = null;Optional<Dog> opt = Optional.fromNullable(dog);
Dog dog2 = opt.or( new Dog("noname", ...) ); assertEquals( "noname", dog2.getName() );
![Page 87: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/87.jpg)
Functional Programming
todo
![Page 88: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/88.jpg)
Super chien
Dog
![Page 89: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/89.jpg)
public class SuperChien implements SuperHero {
private String surnom ; private double poids ; private Set<String> couleursCostume ; private Set<String> pouvoirs ;
...
Supe
r Chi
en 5
Les héros peuvent avoir plusieurs costumes donc je n’utilise pas un ImmutableSet. Idem pour les pouvoirs
dont la liste augmente avec l’expérience.
![Page 90: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/90.jpg)
Tran
sfor
mati
on List<SuperChien> superChiens = Lists.transform(dogs, new Function<Dog, SuperChien>() { @Override public SuperChien apply(Dog dog) { SuperChien chien = new SuperChien();
chien.setSurnom("Super " + dog.getName()); chien.setPoids(dog.getWeight()); chien.setCouleursCostume(newHashSet(dog.getColors())) chien.setPouvoirs(newHashSet("Code en Java", "Vole")) ...
return chien; }});
[Super Milou, Super Rintintin, Super Volt, Super Lassie, Super Pluto, Super Medor]
< Transformation >
G
![Page 91: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/91.jpg)
List<SuperChien> superChiens = Lists.transform(dogs, new Function<Dog, SuperChien>() { @Override public SuperChien apply(Dog dog) { SuperChien chien = new SuperChien(); ... return chien; } });
Vue (lazy) size / isEmpty dispo Pas pour traitements répétés FAQ 3
List<SuperChien> chiens = newArrayList(Lists.transform(...
ImmutableList<SuperChien> chiens =ImmutableList.copyOf(Lists.transform(...
Tran
sfor
mati
on< Transformation >
G
![Page 92: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/92.jpg)
Filtr
e Predicate<Dog> malePredicate = new Predicate<Dog>() { public boolean apply(Dog dog) { return dog.getSex() == MALE; } }
Iterable<Dog> maleDogs = Iterables.filter(dogs, malePredicate);
< Filtre >
G
G[Milou, Rintintin, Volt, Pluto, Medor]
![Page 93: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/93.jpg)
Filtr
e Predicate<Dog> malePredicate = new Predicate<Dog>() { public boolean apply(Dog dog) { return dog.getSex() == MALE; } }
Iterable<Dog> maleDogs = Iterables.filter(dogs, malePredicate);
Dog firstMaleDog = Iterables.find(dogs, malePredicate);
< Filtre >
G
G[Milou, Rintintin, Volt, Pluto, Medor]
GMilou
![Page 94: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/94.jpg)
Filtr
e Predicate<Dog> malePredicate = new Predicate<Dog>() { public boolean apply(Dog dog) { return dog.getSex() == MALE; } }
Iterable<Dog> maleDogs = Iterables.filter(dogs, malePredicate);
Dog firstMaleDog = Iterables.find(dogs, malePredicate);
Dog firstMaleDog = Iterables.find(femaleDogs, malePredicate, DEFAULT_DOG );
Default dog
< Filtre >
G
GGMilou
[Milou, Rintintin, Volt, Pluto, Medor]
![Page 95: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/95.jpg)
Pas
fluen
tPredicate<Dog> malePredicate = new Predicate<Dog>() { public boolean apply(Dog dog) { return dog.getSex() == MALE; }};
Function<FullDog, String> nameFunction = new Function<FullDog, String>() { public String apply(FullDog dog) { return dog.getName(); }};
Iterable<FullDog> maleDogs = Iterables.filter(dogs, malePredicate);
Iterable<String> maleNames = Iterables.transform(maleDogs, nameFunction);
[Milou, Rintintin, Volt, Pluto, Medor]
< Fluent or not fluent ? >
GGG
![Page 96: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/96.jpg)
Pas
fluen
tIterable<FullDog> maleDogs = Iterables.filter(dogs, malePredicate);
Iterable<String> maleNames = Iterables.transform(maleDogs, nameFunction);
[Milou, Rintintin, Volt, Pluto, Medor]
List<String> maleNames2 = FluentIterable.from(dogs) .filter(malePredicate) .transform(nameFunction) .toImmutableList();
Flue
nt
Guava 12.0
< Fluent or not fluent ? >
G
G
http://blog.developpez.com/guava/p11092/annotation/fluentiterable-sur-mon-chien-guava/
![Page 97: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/97.jpg)
Cache
todo
![Page 98: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/98.jpg)
Web
Ser
vice public class DogService {
@Inject private PetShopWebService service;
public Integer getNumberDogsSoldYesterday() { return service.checkSales( "dog" ); }
< Memoization >
5
![Page 99: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/99.jpg)
Web
Ser
vice public class DogService {
@Inject private PetShopWebService service;
public Integer getNumberDogsSoldYesterday() { return service.checkSales( "dog" ); }
< Memoization >
5Ca
che
man
uel
private Integer nbOfDogsSold;
public Integer getNumberDogsSoldYesterday() { if (nbOfDogsSold == null) { nbOfDogsSold = service.checkSales( "dog" ); } return nbOfDogsSold; }
5Double check null…
![Page 100: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/100.jpg)
Gua
va public class DogService { @Inject private PetShopWebService service;
private Supplier<Integer> nbOfDogsSoldSupplier = Suppliers.memoize( new Supplier<Integer>() { public Integer get() { return service.checkSales( "dog" ); } });
public Integer getNumberDogsSoldYesterday() { return nbOfDogsSoldSupplier.get(); }
< Memoization >
G
![Page 101: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/101.jpg)
Gua
va public class DogService { @Inject private PetShopWebService service;
private Supplier<Integer> nbOfDogsSoldSupplier = Suppliers.memoizeWithExpiration( new Supplier<Integer>() { public Integer get() { return service.checkSales( "dog" ); } }, 1, TimeUnit.DAYS );
public Integer getNumberDogsSoldYesterday() { return nbOfDogsSoldSupplier.get(); }
< Memoization >
G
![Page 102: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/102.jpg)
Web
Ser
vice public class DogService {
@Inject private PetShopWebService service;
private Map<String, Dog> dogMap = Maps.newHashMap();
public Integer getDog(String name) { Dog dog = dogMap.get(name); if(dog == null) { dog = service.getAnimal( "dog", name ); // type-name dogMap.put( name, dog ); } return dog; }
< Cache >
5
Quid du timeout ? Max ?
![Page 103: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/103.jpg)
Gua
va public class DogService { @Inject private PetShopWebService service;
private LoadingCache<String, Dog> dogCache = CacheBuilder.newBuilder() .maximumSize(2000) .expireAfterWrite(30, TimeUnit.MINUTES) .build(new CacheLoader<String, Dog>() { public Dog load(String key) { return service.getAnimal( "dog", key ); } });
public Integer getDog(String name) { return dogCache.get( name ); // + try-catch }
< Cache >
G
![Page 104: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/104.jpg)
Hash
Fantôme
![Page 105: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/105.jpg)
Has
h HashFunction hf = Hashing.md5();HashCode hc = hf.newHasher() .putInt(123) .putString("Milou") .hash();
byte[] bytes = hc.asBytes();
md5 Murmur3 128 bits Murmur3 32 bits Sha1 Sha256 Sha512 goodFastHash
G
![Page 106: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/106.jpg)
Prép
arati
on int NB_OF_DOGS = 100000;List<Dog> dogs = newArrayList();Random rand = new Random();for (int i = 0; i < NB_OF_DOGS; i++) { Dog dog = new Dog(); dog.setName("abc" + rand.nextInt(999)); ... dogs.add(dog);}
dogs.add(milou);
boolean isInList = dogs.contains(milou);true (14 ms)
final Dog milou = new Dog();milou.setName("Milou");...
boolean isInList = dogs.contains(milou); false (14 ms)cont
ains
< Is in list ? >
5
5
![Page 107: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/107.jpg)
Bloo
m fi
lter
Funnel<Dog> dogFunnel = new Funnel<Dog>() { public void funnel(Dogdog, PrimitiveSink sink) { sink.putString(dog.getName()) .putString(dog.getFullName()) .putString(dog.getRace()); }};
BloomFilter<Dog> bloom = BloomFilter.create(dogFunnel, NB_OF_DOGS, 0.01);
for (int i = 0; i < NB_OF_DOGS; i++) { ... bloom.put(dog);
bloom.put(milou);
boolean isInList = bloom.mightContain(milou);true (0 ms)
boolean isInList = bloom.mightContain(milou);false (0 ms)
< Is in list ? >
G
http://blog.developpez.com/guava/p11149/collection/bloom-filter-de-guava-13/
Guava 13
![Page 108: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/108.jpg)
Guava or not Guava ?
Avantages et inconvénients
![Page 109: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/109.jpg)
Pro
/ Co
ns Ne pas en abuser…
Utile Bonnes pratiques
![Page 110: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/110.jpg)
LIEN
S @thierryleriche
![Page 111: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/111.jpg)
Guava http://code.google.com/p/guava-libraries
Lombok http://projectlombok.org
Lombok-pg https://github.com/peichhorn/lombok-pg
![Page 112: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/112.jpg)
ICAUDAhttp://icauda.comhttp://icauda.com/articles.html (articles)http://icauda.com/cours.html (slides)
Blog Guavahttp://blog.developpez.com/guava
« Simplifier le code de vos beans Java à l'aide de Commons Lang, Guava et Lombok »http://thierry-leriche-dessirier.developpez.com/tutoriels/ java/simplifier-code-guava-lombok (article)
![Page 113: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/113.jpg)
MER
CI
![Page 114: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/114.jpg)
FAQ
/ B
onus
1. Guava Vs Commons 2. Régime façon Apache 3. Fonctionnal prog Vs boucle for 4. Créer des Maps5. Charsets6. Converter Spring7. Orderings8. Licences9. Extension avec valeurs10. Chrono11. CharMatcher12. Impl13. And, or, in…14. Partition, limit15. Inférence de type16. Coût du bloom17. Ecrasement des getters existants
![Page 115: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/115.jpg)
Guava Vs Commons ?
http://tinyurl.com/guava-vs-apache
1
![Page 116: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/116.jpg)
Régime : la méthode Commons ?
2
public String toString() {
return new ToStringBuilder(this) .append("id", id) .append("name", name) .append("fullName", fullName) ... .append("colors", colors) .toString();}
toSt
ring
L
![Page 117: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/117.jpg)
Régime : la méthode Commons ?
2
public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (!(obj instanceof Dog)) return false;
Dog other = (Dog) obj;
return new EqualsBuilder() .append(birthday, other.birthday) .append(fullname, other.fullname) .append(name, other.name) .append(race, other.race) .append(sex, other.sex) .isEquals();}
equa
ls L
![Page 118: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/118.jpg)
Régime : la méthode Commons ?
2
public int hashCode() {
return new HashCodeBuilder(17, 37) .append(birthday) .append(fullname) .append(name) .append(race) .append(sex) .toHashCode();}
hash
Code L
![Page 119: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/119.jpg)
Régime : la méthode Commons ?
2
public int compareTo(Dog other) {
return new CompareToBuilder() .append(name, other.name) .append(fullname, other.fullname) .append(birthday, other.birthday) ... .append(sex, other.sex) .toComparison();}
com
pare
To L
![Page 120: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/120.jpg)
List<SuperChien> superChiens = newArrayList();for(Dog dog : dogs) { SuperChien chien = new SuperChien(); ... superChiens.add(chien);}
List<SuperChien> superChiens = newArrayList( Lists.transform(dogs, new Function<Dog, SuperChien>() { @Override public SuperChien apply(Dog dog) { SuperChien chien = new SuperChien(); ... return chien; } }));Tr
ansf
orm
ation
Fonctionnal prog Vs boucle for : quand ?
http://code.google.com/p/guava-libraries/wiki/FunctionalExplained
Vs3 G
G
![Page 121: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/121.jpg)
Créer des Maps
4
of
public static final ImmutableMap<String, Integer> AGES = new ImmutableMap.Builder<String, Integer>() .put("Milou", 32) .put("Volt", 7) .put("Pluto", 37) .put("Lassie", 17) .put("Medor", 5) .put("Croquette", 8) .put("Loulou", 2) ... .build();
public static final ImmutableMap<String, Integer> AGES = ImmutableMap.of("Milou", 32, "Volt", 7, "Pluto", 37, "Lassie", 17);
Build
er
G
G
![Page 122: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/122.jpg)
Charsets
5
Java
5
String name = "Milou";
byte[] bytes = name.getBytes(Charsets.UTF_8);
String name = "Milou";
try { byte[] bytes = name.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) { throw new AssertionError(e);}
Gua
va
Ca n’arrive jamais cette exception
5
G
![Page 123: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/123.jpg)
import org.springframework...Converter;
@Component("dogToChienConverter")public class DogToChienConverter implements Converter<List<Dog>, List<SuperChien>> {
public List<SuperChien> convert(List<Dog> dogs) { List<SuperChien> chiens = newArrayList(transform(dogs, new Function<Dog, SuperChien>() { public SuperChien apply(Dog dog) { ... return chien; } })); return chiens; }6
Converter Spring
Lazy or not lazy ?
G
![Page 124: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/124.jpg)
Orderings
7
![Page 125: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/125.jpg)
Licences
8
Lombok : MIT License Lombok-pg : MIT License
Guava : Apache License 2.0
Commons : Apache License 2.0
![Page 126: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/126.jpg)
@ExtensionMethod({ Object.class, MyOtherClass.class })public class DogWithExtension {
public void foo() { String s1 = "toto"; s1.print(); // toto
String s2 = null; s2.print(); // null }}
class MyOtherClass { public static <T> void print(final T value) { System.out.println(value); }}
L
On peut mettre autre chose qu’un "Object", par exemple un "Arrays" , un "Dog" , etc.
9
Extension avec valeurs
![Page 127: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/127.jpg)
@ExtensionMethod({ Object.class, MyOtherClass.class })public class DogWithExtension {
public void foo() { String s1 = "toto"; s1.print(); // toto
String s2 = null; s2.print(); // null s2.print("vide"); // vide }}
class MyOtherClass { public static <T> void print(final T value) { System.out.println(value); }
public static void print(String value, String other) { if (value == null || value.isEmpty()) { System.out.println(other); } else { System.out.println(value); }
9
Extension avec valeurs
L
![Page 128: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/128.jpg)
long start = new Date().getTime();
foo(); // traitement long (ou pas)
long end = new Date().getTime();
long duration = end - start; // 11 ms
Java
5 5< Chrono >
10
Stopwatch sw = new Stopwatch();sw.start();
foo(); // traitement long (ou pas)
sw.stop();long duration = sw.elapsedMillis(); // 11 ms
G
Gua
va
long nano = sw.elapsedTime(NANOSECONDS); // 11179739 nslong micro = sw.elapsedTime(MICROSECONDS); // 11179 uslong millis = sw.elapsedTime(MILLISECONDS); // 11 ms
http://blog.developpez.com/guava/p11160/base/le-stop-watch-de-guava/
![Page 129: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/129.jpg)
CharMatcher
11
![Page 130: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/130.jpg)
Impl
12
public class Dog implements Comparable<Dog> {
private Integer id ; private String name ; private String fullName ;
...
@Override public int compareTo(Dog dog) { return ...; }
implements List ? aie aie aie
5
![Page 131: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/131.jpg)
Impl
12
@AutoGenMethodStubpublic class Dog implements Comparable<Dog> {
private Integer id ; private String name ; private String fullName ;
...
L
![Page 132: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/132.jpg)
List<Dog> dogs2 = newArrayList( new Dog("Rintintin", 45.0, MALE, ...),
new Dog("Pluto", 22.0, MALE, ...),
new Dog("Lulu", 35.6, MALE, ...));
Seco
nde
liste G
[Rintintin, Pluto, Lulu]
[Milou, Rintintin, Volt, Lassie, Pluto, Medor]
Liste 2 : dogs2
Liste 1 : dogs
13
And, or, in…
![Page 133: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/133.jpg)
And, or, in…
13
And,
or,
in... import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.in;
boolean isRintintinInBoth = and( in(dogs), in(dogs2) ) .apply(new Dog("Rintintin"));
true
import static com.google.common.base.Predicates.or;
boolean isTintinInOne = or( in(dogs), in(dogs2) ) .apply(new Dog("Tintin");
false
G
G
[Rintintin, Pluto, Lulu]
[Milou, Rintintin, Volt, Lassie, Pluto, Medor] Li
ste
2 : d
ogs2
List
e 1
: dog
s
![Page 134: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/134.jpg)
Partition, limit
14
Parti
tion
List<List<FullDog>> partition = Lists.partition(dogs, 4);
[Milou, Rintintin, Volt, Lassie]
[Pluto, Medor]
List<FullDog> first4Dogs = newArrayList(Iterables.limit(dogs, 4));
[Milou, Rintintin, Volt, Lassie]
G
GLim
it
![Page 135: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/135.jpg)
Inférence de type
15
Java
List<Integer> primeNumbers = new ArrayList<Integer>();
List<Integer> primeNumbers = newArrayList();
Gua
va
public static <E> ArrayList<E> newArrayList() { return new ArrayList<E>();}
http://blog.developpez.com/guava/p11334/collection/inference-de-type-avec-guava
![Page 136: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/136.jpg)
Coût du bloom
16
final List<DogGuava> dogs = Lists.newArrayList();
final Funnel<DogGuava> dogFunnel = new Funnel<DogGuava>() { @Override public void funnel(DogGuava dog, PrimitiveSink sink) { sink.putString(dog.getName()) .putString(dog.getFullName()) .putString(dog.getRace()); }};BloomFilter<DogGuava> bloom = BloomFilter.create(dogFunnel, NB_OF_DOGS, 0.01);
final Random rand = new Random();
Stopwatch sw = new Stopwatch();sw.start();
for (int i = 0; i < NB_OF_DOGS; i++) { final DogGuava dog = new DogGuava(...); dogs.add(dog);}
long duration1 = sw.elapsedTime(MICROSECONDS);
![Page 137: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/137.jpg)
Coût du bloom
16
for (DogGuava dog : dogs) {bloom.put(dog);
}long duration2 = sw.elapsedTime(MICROSECONDS);
boolean inside = dogs.contains(milou);long duration3 = sw.elapsedTime(MICROSECONDS);
Chiens Add to list Add to bloom Recherche
1 828 17 971 430
10 938 26 643 749
100 2 159 21 859 754
1 000 9 312 49 564 1 192
10 000 42 232 126 505 5 613
100 000 156 065 261 168 14 353
1 000 000 1 594 113 775 300 41 904
![Page 138: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/138.jpg)
Pas d’écrasement des getters existants
17
@Datapublic class MicroDog {
private String name; private Integer age;
public String getName() { return "*" + name + "*"; }}
@Testpublic void testGetterExistant() { final String name = "Milou"; final String requiredName = "*Milou*";
final MicroDog dog = new MicroDog(); dog.setName(name);
assertEquals(requiredName, dog.getName());}
![Page 139: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/139.jpg)
Slides en préparation
![Page 140: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/140.jpg)
I/O
todo
![Page 141: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/141.jpg)
public void lireJava6(String from) { InputStream in = null; try { in = new FileInputStream(from); byte[] b = new byte[10000]; while (true) { int r = in.read(b); if (r == -1) break; ... } } catch (Exception e) { ... } finally { if (in != null) { try { in.close(); } catch (Exception e) { ... } } ...
Ress
ourc
es 5< I/O >
![Page 142: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/142.jpg)
public void lireJava7(String from) { try(InputStream in = new FileInputStream(from)) { ... while (true) { ... } }}
Java
7 7< I/O >
![Page 143: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/143.jpg)
Todo
Gua
va G< I/O >
![Page 144: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/144.jpg)
Concurrent / future
todo
![Page 145: Soirée Guava et Lombok avec Thierry Leriche](https://reader031.vdocuments.net/reader031/viewer/2022013111/5560b511d8b42afe3b8b494e/html5/thumbnails/145.jpg)
Todo