SlideShare une entreprise Scribd logo
1  sur  138
Milou fait un régime
 Guava - Lombok
SPONSORS
@thierryleriche

                       Thierry Leriche-Dessirier
                     Consultant JEE freelance
                     Professeur de Génie Logiciel à l’ESIEA
                     Rédacteur pour Programmez
                     Rédacteur pour Developpez.com
icauda.com
Cours                  Forums


FAQ                    News


Interviews             Critiques


Articles / tutoriels   Agendas


Magazine
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
 Milou est trop lourd (intro)
Agenda

      Lombok (et Lombok-pg) en action

      Tour d’horizon de Guava
Milou est trop lourd (et doit faire un régime)



       I am Milou
5
DOG
      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 ;
       ...
   Constructeurs
                  Getters / setters
                  toString ()
                  equals ()
                  hashCode ()
                  compareTo ()


   id
   name
   fullName
   sex
   birthday
   race
   lof
   weight
   size
   Colors
   Constructeurs
                              Getters / setters
                              toString ()
                              equals ()
                              hashCode ()
                              compareTo ()


   id
   name       clic clic
   fullName    démo
   sex
   birthday
   race
   lof
   weight
   size
   Colors
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 ?...
    Constructeurs
                   Getters / setters
                   toString ()
                   equals ()
                   hashCode ()
                   compareTo ()




                   10 attributs          210 lignes
   id
   name
   fullName
   sex
   birthday
   race
   lof
   weight
   size
   Colors
10 attributs
Java   210 lignes de code
Va chercher Guava 
                                   toString ()
                                   equals ()
                                   hashCode ()
                                   compareTo ()




                      Commons  FAQ 1-2
Base


       Objects
Java 5
     public String toString() {
       return "Dog [id=" + id
         + ", name=" + name
         + ", fullName=" + fullName
                                                                    5
         + ", sex=" + sex
         + ", birthday=" + birthday
         + ", race=" + race
         + ", lof=" + lof
         + ", weight=" + weight
         + ", size=" + size
         + ", colors=" + colors + "]";
     }
                                         Simple, efficace et bien pourri 




             toString ()
Java 5
     public String toString() {
       StringBuilder sb = new StringBuilder();
         sb.append(Dog.class.getSimpleName())
           .append("[id=").append(id)
                                                               5
           .append(", name=").append(name)
           .append(", fullName=").append(fullName)
           ...
           .append(", colors=").append(colors);
         return sb.toString();
     }
                                              Mieux mais sans plus 




               toString ()
Guava
    public String toString() {
      return Objects.toStringHelper(this)
               .add("id", id)
               .add("name", name)
                                            G
               .add("fullName", fullName)
               ...
               .add("colors", colors)
               .toString();
    }
                                            Builder




            toString ()
birthday, fullname, name, race et sex
Java 5
     public boolean equals(Object obj) {
       if (this == obj) return true;
       if (obj == null) return false;
       if (getClass() != obj.getClass()) return false;
                                                                         5
         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;
     }

                                                          Carrément illisible 


                equals ()
birthday, fullname, name, race et sex
Guava
    public boolean equals(Object obj) {
      if (!(obj instanceof Dog)) return false;
        Dog other = (Dog) obj;
                                                                  G
        return Objects.equal(birthday, other.birthday)
               && Objects.equal(fullname, other.fullname)
               && Objects.equal(name, other.name)
               && Objects.equal(race, other.race)
               && sex == other.sex;
    }




              equals ()
birthday, fullname, name, race et sex
Java 5
     public int hashCode() {
       final int prime = 31;
       int result = 1;
         result = prime * result
                                                                         5
             + ((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;
     }




                hashCode ()
birthday, fullname, name, race et sex
Guava
    public int hashCode() {



    }
        return Objects.hashCode(birthday, fullName,
                                name, race, sex);
                                                                  G



              hasCode()
name, fullname, birthday, weight, size, race et sex
Java 5
     public int compareTo(Dog other) {
       int result = 0;
         result = name.compareTo(other.name);
         if (result != 0) {
                                                                             5
           return result;
         }
         result = fullname.compareTo(other.fullname);
         if (result != 0) {
           return result;
         }
         ...
     }




                compareTo ()
name.compareTo(other.name)



                 Vsother.name.compareTo(name)




 compareTo ()
name, fullname, birthday, weight, size, race et sex
Guava
    public int compareTo(Dog other) {
      return ComparisonChain.start()
               .compare(name, other.name)
               .compare(fullName, other.fullName)
               .compare(birthday, other.birthday)
                                                                          G
               .compare(weight, other.weight)
               .compare(size, other.size)
               .compare(race, other.race)
               .compare(sex, other.sex)
               .result();
    }




               compareTo ()
Lombok




     en action
Régime


         Annotations de base
Régime    @NoArgsConstructor /
           @RequiredArgsConstructor /
           @AllArgsConstructor  constructeurs
          @Getter / @Setter
          @ToString
          @EqualsAndHashCode
          @Data  @Getter + @Setter + @ToString +
                      @EqualsAndHashCode + @RequiredArgsConstructor
Régime                @NoArgsConstructor /
                       @RequiredArgsConstructor /
                       @AllArgsConstructor
                      @Getter / @Setter
                      @ToString
                      @EqualsAndHashCode
                      @Data
         clic clic
          démo
10 attributs
  Java   210 lignes de code
Lombok   12 lignes + 2-3 @ + compareTo()
Factory
      @RequiredArgsConstructor(staticName = "of")
      public class Dog {
          private Integer id;
          @NonNull private String name; 
                                                         L
          private String fullName;
          @NonNull private SexeEnum sex; 
          private Date birthday;
          ...
                                                    name, sex
      Dog dog = Dog.of("Milou", MALE);
Factory
      @RequiredArgsConstructor(staticName = "of")
      public class Dog {
          private Integer id;
          @NonNull private String name; 
                                                                 L
          private String fullName;
          @NonNull private SexeEnum sex; 
          private Date birthday;
          ...
                                                            name, sex
      Dog dog = Dog.of("Milou", MALE);

      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);
      }
Trucs pratiques


                  Se simplifier la vie
Pratique      @Cleanup
              @Synchronized
              @SneakyThrows
              @Log
              @Delegate

            val
Ressources
         public void lireJava6(String from) {
           InputStream in = null;
           try {
             in = new FileInputStream(from);
             byte[] b = new byte[10000];
                                                5
             while (true) {
               int r = in.read(b);
               if (r == -1)
                  break;
                 ...
             }
           } catch (Exception e) {
             ...
           } finally {
             if (in != null) {
               try {
                  in.close();
               } catch (Exception e) {
                  ...
               }
             }
           ...
Ressources
         public void lire(String from) throws IOException {
             @Cleanup
             InputStream in = new FileInputStream(from);
             byte[] b = new byte[10000];
                                                              L
             while (true) {
               int r = in.read(b);
               if (r == -1)
                 break;
                 ...
             }
         }
Délombok


           Revenir sans la lib
java -jar lombok.jar delombok src -d src-delomboked

Délombok
       <properties>
         <lombok.sourceDirectory>
           ${project.basedir}/src/main/java
         </lombok.sourceDirectory>
       ...
                                                XML
       <build>
         <groupId>org.projectlombok</groupId>
         <artifactId>maven-lombok-plugin</artifactId>
         <executions>
           <execution>
             <phase>generate-sources</phase>
           </execution>
         </executions>
         ...




                    mvn lombok:delombok
Délombok
       @Data
       public class Dog {
                                 5
                                                                        5
         private Integer id;
                                  public class Dog {
         private String name;
                                    private Integer id;
         private String fullName;
                                    private String name;
         private SexeEnum sex;
                                    private String fullName;
         private Date birthday;
                                    ...
         private String race;
                                    private List<String> colors;
         private Boolean lof;
         private Double weight;     public DogLombok() {
         private Double size;       }
         private List<String> colors;
                                    @java.lang.Override
       }
                                    @java.lang.SuppressWarnings("all")
                                    public boolean equals(final java.lang.Obje
                                      if (o == this) return true;
                        mvn           if (o == null) return false;
                  lombok:delombok     if (o.getClass() != this.getClass()) ret
                                      final Dog other = (Dog)o;
                                      if (this.getId() == null ? other.getId()
                                      ...
                                   @java.lang.Override
                                   @java.lang.SuppressWarnings("all")
                                   public int hashCode() {
                                     final int PRIME = 31;
                                     int result = 1;
                                     result = result * PRIME + (this.getId()
Lombok-pg


      Annotations supplémentaires
Annotations Pg
                    @Action                        @Builder
                    @Function                      @LazyGetter
                    @EnumId                        @FluentSetter
                    @Rethrow / @Rethrows           @Predicate
                    @Singleton
                    @AutoGenMethodStub
                    @BoundPropertySupport / @BoundSetter
                    @DoPrivileged
                    @ExtensionMethod
                    @ListenerSupport
                    @WriteLock / @ReadLock
                    @Await / @Signal / @AwaitBeforeAndSignalAfter
                    @Sanitize.Normalize / .With
                    @SwingInvokeLater / @SwingInvokeAndWait
                    @Validate.NotEmpty / .NotNull / .With
                    @VisibleForTesting
Fluent
     @FluentSetter
     @Getter
     public class Dog {
         private Integer id ;
                                                 L
         private String name ;
         private String fullName ;
         ...


     DogLombok dog = new DogLombok();
         dog.name("Milou").sex(MALE);



         println( dog.getName());   //  Milou
         println( dog.getSex());    //  MALE
Builder
      @Builder
      @Getter
      public class Dog {
          private Integer id ;
                                                              L
          private String name ;
          private String fullName ;
          ...


      Dog dog = Dog.dog().name("Milou").sex(MALE).build();


          println( dog.getName());   //  Milou
          println( dog.getSex());    //  MALE
extension
        @ExtensionMethod({ Dog.class, MyDogExtensionClass.class })
        public class DogWithExtension {
            public void foo() {
              Dog milou = new Dog("Milou", 12.5, ...);
                                                                                                     L
              boolean isTooFat = milou.isTooFat();
            }
        }
        class MyDogExtensionClass {
            public static boolean isTooFat(final Dog dog) {
              double imc = dog.getWeight() / pow(dog.getSize(), 2);
              return 25 < imc;
            }
        }




              Avec paramètres  FAQ 9
               http://blog.developpez.com/todaystip/p11165/dev/java/extensionmethod-de-lombok-pg/
Lombok or not Lombok ?


              Avantages et inconvénients
Pro / Cons
                Byte code modifié 
                Version en 0.x
                Documentation des prog ?
                Magique ?



                Compacité
                Lecture simplifiée
                Code normée
                Délombok (pour essayer)
Guava




    tour d’horizon
Factory Methods


              Les choses que j’aime
< new Vs static factories >

Java 5
     List<Integer> primeNumbers = new ArrayList<Integer>();
     Set<String> colors = new TreeSet<String>();
                                                              5
     Map<String, Integer> ages = new HashMap<String, Integer>();
< new Vs static factories >

Java 5  List<Integer> primeNumbers = new ArrayList<Integer>();
        Set<String> colors = new TreeSet<String>();
        Map<String, Integer> ages = new HashMap<String, Integer>();
                                                                              5

                                                                         5
dur dur ?




            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 = ...
< new Vs static factories >

Java 5
     List<Integer> primeNumbers = new ArrayList<Integer>();
     Set<String> colors = new TreeSet<String>();
     Map<String, Integer> ages = new HashMap<String, Integer>();
                                                                                5
                                                                                7
Java 7


     List<Integer> primeNumbers = new ArrayList<>();
     Set<String> colors = new TreeSet<>();
     Map<String, Integer> ages = new HashMap<>();
                                                          Qui utilise Java 7 en prod ?
< new Vs static factories >

Java 5
     List<Integer> primeNumbers = new ArrayList<Integer>();
     Set<String> colors = new TreeSet<String>();
     Map<String, Integer> ages = new HashMap<String, Integer>();
                                                                                  5
                                                                                  7
Java 7


     List<Integer> primeNumbers = new ArrayList<>();
     Set<String> colors = new TreeSet<>();
     Map<String, Integer> ages = new HashMap<>();
                                                              Qui utilise Java 7 en prod ?



                                                                                  G
Guava




         List<Integer> primeNumbers = newArrayList();
         Set<String> colors = newTreeSet();
         Map<String, Integer> ages = newHashMap();
                                                                        Dès maintenant !
< new Vs static factories >

Java 5
     List<Integer> primeNumbers = new ArrayList<Integer>();
     Set<String> colors = new TreeSet<String>();
     Map<String, Integer> ages = new HashMap<String, Integer>();
                                                                                   5
                                                                                   7
Java 7


     List<Integer> primeNumbers = new ArrayList<>();
     Set<String> colors = new TreeSet<>();
     Map<String, Integer> ages = new HashMap<>();
                                                               Qui utilise Java 7 en prod ?



                                                                                   G
Guava




         List<Integer> primeNumbers = newArrayList();
         Set<String> colors = newTreeSet();
         Map<String, Integer> ages = newHashMap();
                                                                         Dès maintenant !
                  Lombok




                       var primeNumbers = new ArrayList<Integer>();
                       -> primeNumbers.size();
                          ...
                                                                                  L
< new Vs static factories >




                                                                             G
List of dogs   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, ...));



                                                                [Milou,
                                                                Rintintin,
                                                                Volt,
                                                                Lassie,
                                                                Pluto,
                                                                Medor]
Immutables


        Pour que ça ne change pas
immutable
Quand ?
immutable
                 Quand ?           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.
< unmodifiables Vs immutables >

Java 5
     Set<Integer> temp =
        new LinkedHashSet<Integer>(Arrays.asList(1, 2, 3, 5, 7));
     Set<Integer> primes = Collections.unmodifiableSet(temp);
< unmodifiables Vs immutables >

Java 5
     Set<Integer> temp =
        new LinkedHashSet<Integer>(Arrays.asList(1, 2, 3, 5, 7));
     Set<Integer> primes = Collections.unmodifiableSet(temp);




                                                                 G
Guava




         Set<Integer> primes = ImmutableSet.of(1, 2, 3, 5, 7);
< unmodifiables Vs immutables >

Of
 ImmutableSet.of(E
 ImmutableSet.of(E
 ImmutableSet.of(E
 ImmutableSet.of(E
 ImmutableSet.of(E
                                e1)
                                e1,
                                e1,
                                e1,
                                e1,
                                       E
                                       E
                                       E
                                       E
                                           e2)
                                           e2,
                                           e2,
                                           e2,
                                                 E
                                                 E
                                                 E
                                                     e3)
                                                     e3, E e4)
                                                     e3, E e4, E e5)
                                                                                         G
 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

           http://blog.developpez.com/guava/p10589/collection/title-212/
< Copie de défense >
Java 5   public class Dog {
          private String name;
          ...
          private List<String> colors;
                                                               5
          public Dog(String name, List<String> colors) {
            this.name = name;
            ...
            this.colors = Collections.unmodifiableList(
                             new ArrayList<String>(colors));
          }
          public List<String> getColors() {
            return colors;
          }
< Copie de défense >
Guava   public class Dog {
         private String name;
         ...
         private ImmutableList<String> colors;
                                                           G
         public Dog(String name, List<String> colors) {
           this.name = name;
           ...
           this.colors = ImmutableList.copyOf(colors);
         }
         public ImmutableList<String> getColors() {
           return colors;
         }




                             Message clair
Collections en plus


              Multimap, Bipap, Multiset
< Multi Map >

Java 5
     Map<String, List<String>> dogFavoriteColors =
       new HashMap<String, List<String>>();
                                                             5
     }
       milouColors = new ArrayList<String>();
       dogFavoriteColors.put("Milou",milouColors);
                                                             5
     List<String> milouColors = dogFavoriteColors.get("Milou");
     if(milouColors == null) {



     milouColors.add("Vert");
< Multi Map >

Java 5
     Map<String, List<String>> dogFavoriteColors =
       new HashMap<String, List<String>>();
                                                             5
     }
       milouColors = new ArrayList<String>();
       dogFavoriteColors.put("Milou",milouColors);
                                                             5
     List<String> milouColors = dogFavoriteColors.get("Milou");
     if(milouColors == null) {



     milouColors.add("Vert");




                                                            G
Guava




         Multimap<String, String> dogFavoriteColors =
           HashMultimap.create();
         dogFvoriteColors2.put("Milou", "Jaune");
         dogFavoriteColors2.put("Milou", "Rouge");
< Bi Map >



                                                                             G
Guava
    BiMap<String, Dog> tatouages = HashBiMap.create();
    tatouages.put("ABC123", new Dog("Milou") );
    tatouages.put("MBD324", new Dog("Volt") );
    tatouages.put("JFT672", new Dog("Lassie") );

    println( tatouages );
                                                 {ABC123=Milou,
                                                 MBD324=Volt,

         ABC123=Milou
    println( tatouages.inverse() );
         Une map bijective
                                                 JFT672=Lassie}

                                                 {Milou=ABC123,

         MDB324=Volt
                                                 Volt=MBD324,
                                                 Lassie=JFT672}



         JFT672=Lassie
         Il est possible de changer la valeur associée à une clé mais pas
         d'avoir deux clés avec la même valeur (IllegalArgumentException).
< Multi Set >


Guava
                                                              G
        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 );
                                       [2, 3 x 2, 5, 7, 11]


        println( ages.count(3) )

                                       2
Base


Préconditions, joiner, splitter, optional
   toString ()
   equals ()
   hashCode ()
   compareTo ()
< Preconditions >


DOG
      public class Dog {
       private Integer
       private String
       private String
                           id ;
                           name ;
                           fullName ;
                                                         5
       ...

       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;
           ...
       }
< Preconditions >


DOG                                                           G
      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");
            ...
        }




         checkNotNull()  NPE
         checkArgument()  IAE
         checkState()     ISE
Joiner
     String names = Joiner.on(", ")
       .join(newArrayList("Lassie", "Volt", "Milou"));

                                           "Lassie, Volt, Milou"
                                                                           G
                                                                   Java classique
          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();
Joiner
     String names = Joiner.on(", ")
       .join(newArrayList("Lassie", "Volt", "Milou"));

                                        "Lassie, Volt, Milou"
                                                                G
         String names = Joiner.on(", ")
           .join(newArrayList("Lassie", "Volt", null, "Milou"));

                                         NPE 
Joiner
     String names = Joiner.on(", ")
       .join(newArrayList("Lassie", "Volt", "Milou"));

                                        "Lassie, Volt, Milou"
                                                                G
         String names = Joiner.on(", ")
           .join(newArrayList("Lassie", "Volt", null, "Milou"));

                                         NPE 
     String names = Joiner.on(", ")
       .skipNulls()
       .join(newArrayList("Lassie", "Volt", null, "Milou"));

                                        "Lassie, Volt, Milou"
                                                                G
Joiner
     String names = Joiner.on(", ")
       .join(newArrayList("Lassie", "Volt", "Milou"));

                                                            "Lassie, Volt, Milou"
                                                                                               G
         String names = Joiner.on(", ")
           .join(newArrayList("Lassie", "Volt", null, "Milou"));

                                                             NPE 
     String names = Joiner.on(", ")
       .skipNulls()
       .join(newArrayList("Lassie", "Volt", null, "Milou"));

                                                            "Lassie, Volt, Milou"
                                                                                               G
                                                                                               G
     String names = Joiner.on(", ")
       .useForNull("Anonymous"))
       .join(newArrayList("Lassie", "Volt", null, "Milou"));

                                                            "Lassie, Volt, Anonymous, Milou"


              http://blog.developpez.com/guava/p11054/base/joiner-pour-assembler-des-items/
Splitter
       Iterable<String> dogNames =
         Splitter.on(",")                         [ "Lassie",
                 .split("Lassie, Volt, Milou");     "Volt",
                                                    "Milou" ]
Splitter
       Iterable<String> dogNames =
         Splitter.on(",")                              [ "Lassie",
                 .split("Lassie, Volt, Milou");          "Volt",
                                                         "Milou" ]
           Iterable<String> dogNames =
             Splitter.on(",")                        [ "Lassie",
                     .split("Lassie, Volt, ,Milou"); "Volt",
                                                        " ",
                                                        "Milou" ]
Splitter
       Iterable<String> dogNames =
         Splitter.on(",")                              [ "Lassie",
                 .split("Lassie, Volt, Milou");          "Volt",
                                                         "Milou" ]
           Iterable<String> dogNames =
             Splitter.on(",")                        [ "Lassie",
                     .split("Lassie, Volt, ,Milou"); "Volt",
                                                        " ",
                                                        "Milou" ]
       Iterable<String> dogNames =
         Splitter.on(",")                        [ "Lassie",
                 .trimResults()                    "Volt",
                 .split("Lassie, Volt, ,Milou"); "",
                                                        "Milou" ]
Splitter
       Iterable<String> dogNames =
         Splitter.on(",")                                                       [ "Lassie",
                 .split("Lassie, Volt, Milou");                                   "Volt",
                                                                                  "Milou" ]
           Iterable<String> dogNames =
             Splitter.on(",")                        [ "Lassie",
                     .split("Lassie, Volt, ,Milou"); "Volt",
                                                                                  " ",
                                                                                  "Milou" ]
       Iterable<String> dogNames =
         Splitter.on(",")                        [ "Lassie",
                 .trimResults()                    "Volt",
                 .split("Lassie, Volt, ,Milou"); "",
                                                                                  "Milou" ]
       Iterable<String> dogNames =
         Splitter.on(",")
                 .trimResults()
                 .omitEmptyStrings()             [ "Lassie",
                 .split("Lassie, Volt, ,Milou"); "Volt",
                                                                                  "Milou" ]
                                                                                                       G
                http://blog.developpez.com/guava/p11045/annotation/splitter-pour-separer-des-items/
Wrapper Optional <T>

Optional
           Dog dog = new Dog("Milou", ...);
           Optional<Dog> opt = Optional.of(dog);
           assertTrue( opt.isPresent() );
           assertEquals( "Milou", opt.get().getName() );
Wrapper Optional <T>

Optional
           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
Wrapper Optional <T>

Optional
           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);
Wrapper Optional <T>

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

                http://blog.developpez.com/guava/p11163/base/le-wrapper-optional-de-guava/
Functional Programming


                         todo
Super chien




Dog
Super Chien
              public class SuperChien implements SuperHero {
               private
               private
               private
                         String
                         double
                         Set<String>
                                          surnom ;
                                          poids ;
                                          couleursCostume ;
                                                                                  5
               private   Set<String>      pouvoirs ;
               ...

                                   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.
< Transformation >

Transformation
             List<SuperChien> superChiens =
               Lists.transform(dogs,

                 @Override
                               new Function<Dog, SuperChien>() {

                 public SuperChien apply(Dog dog) {
                                                                             G
                   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 >

Transformation
                                                                         G
             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(...
< Filtre >

Filtre
     Predicate<Dog> malePredicate =
       new Predicate<Dog>() {
         public boolean apply(Dog dog) {

         }
           return dog.getSex() == MALE;
                                                             G
       }


     Iterable<Dog> maleDogs =
       Iterables.filter(dogs, malePredicate);
                                                [Milou,
                                                Rintintin,
                                                             G
                                                Volt,
                                                Pluto,
                                                Medor]
< Filtre >

Filtre
     Predicate<Dog> malePredicate =
       new Predicate<Dog>() {
         public boolean apply(Dog dog) {

         }
           return dog.getSex() == MALE;
                                                [Milou,
                                                             G
       }                                        Rintintin,
                                                Volt,
     Iterable<Dog> maleDogs =
       Iterables.filter(dogs, malePredicate);
                                                Pluto,
                                                Medor]       G
     Dog firstMaleDog =
       Iterables.find(dogs, malePredicate);
                                                Milou        G
< Filtre >

Filtre
     Predicate<Dog> malePredicate =
       new Predicate<Dog>() {
         public boolean apply(Dog dog) {

         }
           return dog.getSex() == MALE;
                                                [Milou,
                                                              G
       }                                        Rintintin,
                                                Volt,
     Iterable<Dog> maleDogs =
       Iterables.filter(dogs, malePredicate);
                                                Pluto,
                                                Medor]        G
     Dog firstMaleDog =
       Iterables.find(dogs, malePredicate);
                                                Milou         G
     Dog firstMaleDog =
       Iterables.find(femaleDogs, malePredicate, DEFAULT_DOG );

                                                Default dog
G
Seconde liste   List<Dog> dogs2 = newArrayList(
                  new Dog("Rintintin", 45.0, MALE, ...),
                 new Dog("Pluto", 22.0, MALE, ...),
                 new Dog("Lulu", 35.6, MALE, ...));




                      [Rintintin,         [Milou,
                      Pluto,              Rintintin,
                      Lulu]               Volt,
                      Liste 2 : dogs2     Lassie,
                                          Pluto,
                                          Medor]
                                          Liste 1 : dogs
< Fluent or not fluent ? >

Pas fluent
         Predicate<Dog> malePredicate =
           new Predicate<Dog>() {
             public boolean apply(Dog dog) {
               return dog.getSex() == MALE;
             }};
                                                                      G
         Function<FullDog, String> nameFunction =
           new Function<FullDog, String>() {
             public String apply(FullDog dog) {
               return dog.getName();
             }};
                                                                      G
                                                                      G
         Iterable<FullDog> maleDogs =
           Iterables.filter(dogs, malePredicate);
         Iterable<String> maleNames =
           Iterables.transform(maleDogs, nameFunction);
                                                              [Milou,
                                                              Rintintin,
                                                              Volt,
                                                              Pluto,
                                                              Medor]
< Fluent or not fluent ? >

Pas fluent
         Iterable<FullDog> maleDogs =
           Iterables.filter(dogs, malePredicate);
         Iterable<String> maleNames =
           Iterables.transform(maleDogs, nameFunction);
                                                                                                G
                                                                                                G
Fluent



         List<String> maleNames2 =
           FluentIterable.from(dogs)
             .filter(malePredicate)
             .transform(nameFunction)
             .toImmutableList();
                                                                                             Guava 12.0



                                                                                        [Milou,
                                                                                        Rintintin,
                                                                                        Volt,
                                                                                        Pluto,
              http://blog.developpez.com/guava/p11092/annotation/fluentiterable-sur-   Medor]
             mon-chien-guava/
Cache


        todo
< Memoization >

Web Service
          public class DogService {
              @Inject
              private PetShopWebService service;
              public Integer getNumberDogsSoldYesterday() {
                                                              5
                return service.checkSales( "dog" );
              }
< Memoization >

Web Service
           public class DogService {
               @Inject
               private PetShopWebService service;
               public Integer getNumberDogsSoldYesterday() {
                                                                        5
                 return service.checkSales( "dog" );
               }




                                                                        5
Cache manuel




               private Integer nbOfDogsSold;
               public Integer getNumberDogsSoldYesterday() {
                 if (nbOfDogsSold == null) {
                   nbOfDogsSold = service.checkSales( "dog" );
                 }
                 return nbOfDogsSold;
               }
                                                           Double check null…
< Memoization >

Guava
    public class DogService {
        @Inject
        private PetShopWebService service;
        private Supplier<Integer> nbOfDogsSoldSupplier =
                                                           G
          Suppliers.memoize(
            new Supplier<Integer>() {
              public Integer get() {
                return service.checkSales( "dog" );
              }
            });
        public Integer getNumberDogsSoldYesterday() {
          return nbOfDogsSoldSupplier.get();
        }
< Memoization >

Guava
    public class DogService {
        @Inject
        private PetShopWebService service;
        private Supplier<Integer> nbOfDogsSoldSupplier =
                                                           G
          Suppliers.memoizeWithExpiration(
            new Supplier<Integer>() {
              public Integer get() {
                return service.checkSales( "dog" );
              }
            }, 1, TimeUnit.DAYS );
        public Integer getNumberDogsSoldYesterday() {
          return nbOfDogsSoldSupplier.get();
        }
< Cache >

Web Service
          public class DogService {
              @Inject
              private PetShopWebService service;
              private Map<String, Dog> dogMap = Maps.newHashMap();
                                                                        5
              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;
              }
                                                       Quid du timeout ? Max ?
< Cache >

Guava
    public class DogService {
        @Inject
        private PetShopWebService service;
        private LoadingCache<String, Dog> dogCache =
                                                            G
          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
        }
Hash


       Fantôme
Hash
   HashFunction hf = Hashing.md5();
   HashCode hc = hf.newHasher()
                   .putInt(123)
                   .putString("Milou")
                                         G
                   .hash();
   byte[] bytes = hc.asBytes();

          md5
          Murmur3 128 bits
          Murmur3 32 bits
          Sha1
          Sha256
          Sha512
          goodFastHash
< Is in list ? >

Préparation
           int NB_OF_DOGS = 100000;
           List<Dog> dogs = newArrayList();
           Random rand = new Random();
           for (int i = 0; i < NB_OF_DOGS; i++) {
                                                                    5
             Dog dog = new Dog();
             dog.setName("abc" + rand.nextInt(999));
             ...
             dogs.add(dog);
           }




                                                                    5
contains




           final Dog milou = new Dog();
           milou.setName("Milou");
           ...
           boolean isInList = dogs.contains(milou);
                                                         false (14 ms)

           dogs.add(milou);
           boolean isInList = dogs.contains(milou);
                                                         true (14 ms)
< Is in list ? >

Bloom filter
           Funnel<Dog> dogFunnel = new Funnel<Dog>() {
             public void funnel(Dogdog, PrimitiveSink sink) {
               sink.putString(dog.getName())
                   .putString(dog.getFullName())
                   .putString(dog.getRace());
                                                                                                G
             }};
           BloomFilter<Dog> bloom =
             BloomFilter.create(dogFunnel, NB_OF_DOGS, 0.01);
           for (int i = 0; i < NB_OF_DOGS; i++) {
             ...
             bloom.put(dog);

           boolean isInList = bloom.mightContain(milou);
                                                                                      false (0 ms)
           bloom.put(milou);
           boolean isInList = bloom.mightContain(milou);
               Guava 13
                                                                                      true (0 ms)


                http://blog.developpez.com/guava/p11149/collection/bloom-filter-de-guava-13/
Guava or not Guava ?


             Avantages et inconvénients
Pro / Cons
              Ne pas en abuser…



              Utile
              Bonnes pratiques
LIENS
        @thierryleriche
Guava
 http://code.google.com/p/guava-libraries



Lombok
 http://projectlombok.org

Lombok-pg
 https://github.com/peichhorn/lombok-pg
ICAUDA
 http://icauda.com
 http://icauda.com/articles.html           (articles)
 http://icauda.com/cours.html              (slides)


Blog Guava
 http://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)
MERCI
1. Guava Vs Commons



FAQ / Bonus
              2. Régime façon Apache
              3. Fonctionnal prog Vs boucle for
              4. Créer des Maps
              5. Charsets
              6. Converter Spring
              7. Orderings
              8. Licences
              9. Extension avec valeurs
              10. Chrono
              11. CharMatcher
              12. Impl
              13. And, or, in…
              14. Partition, limit
Guava Vs Commons ?




    http://tinyurl.com/guava-vs-apache




1
Régime : la méthode Commons ?

                                                            L
toString   public String toString() {
               return new ToStringBuilder(this)
                            .append("id", id)
                            .append("name", name)
                            .append("fullName", fullName)
                            ...
                            .append("colors", colors)
                            .toString();
           }




2
Régime : la méthode Commons ?

                                                              L
equals   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();
         }


2
Régime : la méthode Commons ?

                                                     L
hashCode   public int hashCode() {
               return new HashCodeBuilder(17, 37)
                            .append(birthday)
                            .append(fullname)
                            .append(name)
                            .append(race)
                            .append(sex)
                            .toHashCode();
           }




2
Régime : la méthode Commons ?

                                                                 L
compareTo   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();
            }




2
Fonctionnal prog Vs boucle for : quand ?
Transformation
             List<SuperChien> superChiens = newArrayList(
               Lists.transform(dogs, new Function<Dog, SuperChien>() {
                 @Override
                 public SuperChien apply(Dog dog) {
                   SuperChien chien = new SuperChien();
                   ...


             }));
                 }
                   return chien;

                                                                                     G
                                           Vs
                      List<SuperChien> superChiens = newArrayList();


 3                    for(Dog dog : dogs) {
                        SuperChien chien = new SuperChien();


                      }
                        ...
                        superChiens.add(chien);
                                                                                     G
                 http://code.google.com/p/guava-libraries/wiki/FunctionalExplained
Créer des Maps
          public static final ImmutableMap<String, Integer>
of
            AGES = ImmutableMap.of("Milou", 32,


                                                          G
                              "Volt", 7,
                              "Pluto", 37,
                              "Lassie", 17);

          public static final ImmutableMap<String, Integer>
Builder




            AGES = new ImmutableMap.Builder<String, Integer>()
                    .put("Milou", 32)
                    .put("Volt", 7)
                    .put("Pluto", 37)
                    .put("Lassie", 17)


4
                    .put("Medor", 5)
                    .put("Croquette", 8)


                                                          G
                    .put("Loulou", 2)
                    ...
                    .build();
Charsets
Java 5   String name = "Milou";
         try {
           byte[] bytes = name.getBytes("UTF-8");
         } catch (UnsupportedEncodingException e) {
                                                                  5
           throw new AssertionError(e);
         }
                                   Ca n’arrive jamais cette exception 



                                                                G
Guava




         String name = "Milou";
         byte[] bytes = name.getBytes(Charsets.UTF_8);



5
Converter Spring

                                                            G
    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     }
                                                 Lazy or not lazy ?
Orderings




7
Licences

     Lombok :      MIT License
     Lombok-pg :   MIT License

     Guava :       Apache License 2.0

     Commons :     Apache License 2.0




8
Extension avec valeurs

                                                                    L
@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);
  }


9
}




        On peut mettre autre chose qu’un "Object", par exemple un
        "Arrays" , un "Dog" , etc.
Extension avec valeurs
    @ExtensionMethod({ Object.class, MyOtherClass.class })
    public class DogWithExtension {
        public void foo() {
          String s1 = "toto";
                                                                 L
          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);



9
      }

        public static void print(String value, String other) {
          if (value == null || value.isEmpty()) {
            System.out.println(other);
          } else {
            System.out.println(value);
          }
< Chrono >
           long start = new Date().getTime();


 Guava Java 5
           foo(); // traitement long (ou pas)
           long end = new Date().getTime();
                                                                                    5
           long duration = end - start; // 11 ms



           Stopwatch sw = new Stopwatch();
           sw.start();
           foo();
           sw.stop();
                                                                                    G
           long duration = sw.elapsedMillis(); // 11 ms




10
           long nano = sw.elapsedTime(NANOSECONDS); // 11179739 ns
           long micro = sw.elapsedTime(MICROSECONDS); // 11179 us
           long millis = sw.elapsedTime(MILLISECONDS); // 11 ms




            http://blog.developpez.com/guava/p11160/base/le-stop-watch-de-guava/
CharMatcher




11
Impl
 public class Dog implements Comparable<Dog> {
  private Integer id ;
  private String name ;
  private String fullName ;
                                                            5
  ...
  @Override
  public int compareTo(Dog dog) {
    return ...;
  }

                                     implements List ? aie aie aie


12
Impl
 @AutoGenMethodStub
 public class Dog implements Comparable<Dog> {
  private Integer id ;
  private String name ;
                                                 L
  private String fullName ;
  ...




12
And, or, in…
And, or, in...
                                                                                                          G
                 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



                                                                                                          G
                 import static com.google.common.base.Predicates.or;

                 boolean isTintinInOne =
                   or( in(dogs), in(dogs2) )
                     .apply(new Dog("Tintin");
                                                                                                  false


13                                            [Milou,
                                              Rintintin,
                                                                  Liste 2 : dogs2
                             Liste 1 : dogs




                                              Volt,
                                              Lassie,                               [Rintintin,
                                              Pluto,                                Pluto,
                                              Medor]                                Lulu]
Partition, limit
Partition   List<List<FullDog>> partition =
              Lists.partition(dogs, 4);

                                [Milou,           [Pluto,
                                                               G
                                Rintintin,        Medor]
                                Volt,
                                Lassie]



                                                               G
Limit




            List<FullDog> first4Dogs =
              newArrayList(Iterables.limit(dogs, 4));

                                                  [Milou,

14                                                Rintintin,
                                                  Volt,
                                                  Lassie]
Slides en préparation
I/O


      todo
< I/O >




Ressources
         public void lireJava6(String from) {
           InputStream in = null;
           try {
             in = new FileInputStream(from);
             byte[] b = new byte[10000];
                                                5
             while (true) {
               int r = in.read(b);
               if (r == -1)
                  break;
                 ...
             }
           } catch (Exception e) {
             ...
           } finally {
             if (in != null) {
               try {
                  in.close();
               } catch (Exception e) {
                  ...
               }
             }
           ...
< I/O >




Java 7
     public void lireJava7(String from) {
       try(InputStream in = new FileInputStream(from)) {
         ...
         while (true) {
           ...
                                                           7
         }
       }
     }
< I/O >




Guava
    Todo

                     G
Concurrent / future


                      todo
Todo

Contenu connexe

Similaire à 201209 Lombok & Guava

package com.test;public class Team {    private String teamId;.pdf
package com.test;public class Team {    private String teamId;.pdfpackage com.test;public class Team {    private String teamId;.pdf
package com.test;public class Team {    private String teamId;.pdf
aparnacollection
 
ぐだ生 Java入門第一回(equals hash code_tostring)
ぐだ生 Java入門第一回(equals hash code_tostring)ぐだ生 Java入門第一回(equals hash code_tostring)
ぐだ生 Java入門第一回(equals hash code_tostring)
Makoto Yamazaki
 
Team public class Team {    private String teamId;    priva.pdf
Team public class Team {    private String teamId;    priva.pdfTeam public class Team {    private String teamId;    priva.pdf
Team public class Team {    private String teamId;    priva.pdf
DEEPAKSONI562
 
awesome groovy
awesome groovyawesome groovy
awesome groovy
Paul King
 
CodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical GroovyCodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical Groovy
Codecamp Romania
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
Seri Moth
 

Similaire à 201209 Lombok & Guava (20)

Guava et Lombok au Bordeaux JUG
Guava et Lombok au Bordeaux JUGGuava et Lombok au Bordeaux JUG
Guava et Lombok au Bordeaux JUG
 
Guava et Lombok au Lorraine JUG
Guava et Lombok au Lorraine JUGGuava et Lombok au Lorraine JUG
Guava et Lombok au Lorraine JUG
 
Guava et Lombok au Brezth JUG
Guava et Lombok au Brezth JUGGuava et Lombok au Brezth JUG
Guava et Lombok au Brezth JUG
 
Guava et Lombok au Normandy JUG
Guava et Lombok au Normandy JUGGuava et Lombok au Normandy JUG
Guava et Lombok au Normandy JUG
 
Guava et Lombok au Lyon JUG
Guava et Lombok au Lyon JUGGuava et Lombok au Lyon JUG
Guava et Lombok au Lyon JUG
 
BEKK Teknologiradar - Kotlin
BEKK Teknologiradar - KotlinBEKK Teknologiradar - Kotlin
BEKK Teknologiradar - Kotlin
 
package com.test;public class Team {    private String teamId;.pdf
package com.test;public class Team {    private String teamId;.pdfpackage com.test;public class Team {    private String teamId;.pdf
package com.test;public class Team {    private String teamId;.pdf
 
ぐだ生 Java入門第一回(equals hash code_tostring)
ぐだ生 Java入門第一回(equals hash code_tostring)ぐだ生 Java入門第一回(equals hash code_tostring)
ぐだ生 Java入門第一回(equals hash code_tostring)
 
Kotlin : Happy Development
Kotlin : Happy DevelopmentKotlin : Happy Development
Kotlin : Happy Development
 
Functional programming in java
Functional programming in javaFunctional programming in java
Functional programming in java
 
No excuses, switch to kotlin
No excuses, switch to kotlinNo excuses, switch to kotlin
No excuses, switch to kotlin
 
Kotlin intro
Kotlin introKotlin intro
Kotlin intro
 
Presentatie - Introductie in Groovy
Presentatie - Introductie in GroovyPresentatie - Introductie in Groovy
Presentatie - Introductie in Groovy
 
The Groovy Way
The Groovy WayThe Groovy Way
The Groovy Way
 
Team public class Team {    private String teamId;    priva.pdf
Team public class Team {    private String teamId;    priva.pdfTeam public class Team {    private String teamId;    priva.pdf
Team public class Team {    private String teamId;    priva.pdf
 
The Future of JVM Languages
The Future of JVM Languages The Future of JVM Languages
The Future of JVM Languages
 
awesome groovy
awesome groovyawesome groovy
awesome groovy
 
CodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical GroovyCodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical Groovy
 
Start Writing Groovy
Start Writing GroovyStart Writing Groovy
Start Writing Groovy
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
 

Plus de lyonjug

201303 - Golo
201303 - Golo201303 - Golo
201303 - Golo
lyonjug
 
201303 - Java8
201303 - Java8201303 - Java8
201303 - Java8
lyonjug
 
201305 - Lambda by R. Forax
201305 - Lambda by R. Forax201305 - Lambda by R. Forax
201305 - Lambda by R. Forax
lyonjug
 
201301 - Focus Neo4j
201301 - Focus Neo4j201301 - Focus Neo4j
201301 - Focus Neo4j
lyonjug
 
201301 - Panorama NoSQL
201301 - Panorama NoSQL201301 - Panorama NoSQL
201301 - Panorama NoSQL
lyonjug
 
201209 LT Clojure
201209 LT Clojure201209 LT Clojure
201209 LT Clojure
lyonjug
 
Présentation Granite ds lyon 2011 par William Draï
Présentation Granite ds lyon 2011 par William DraïPrésentation Granite ds lyon 2011 par William Draï
Présentation Granite ds lyon 2011 par William Draï
lyonjug
 
20091020 JPA2
20091020 JPA220091020 JPA2
20091020 JPA2
lyonjug
 

Plus de lyonjug (20)

DIY: Analyse statique en Java
DIY: Analyse statique en JavaDIY: Analyse statique en Java
DIY: Analyse statique en Java
 
Lightning talk LyonJUG février 2016 - Ansible
Lightning talk LyonJUG février 2016 - AnsibleLightning talk LyonJUG février 2016 - Ansible
Lightning talk LyonJUG février 2016 - Ansible
 
Introduction LyonJUG décembre 2015
Introduction LyonJUG décembre 2015Introduction LyonJUG décembre 2015
Introduction LyonJUG décembre 2015
 
Introduction LyonJUG Janvier 2016
Introduction LyonJUG Janvier 2016Introduction LyonJUG Janvier 2016
Introduction LyonJUG Janvier 2016
 
Presentation jug novembre2015
Presentation jug novembre2015Presentation jug novembre2015
Presentation jug novembre2015
 
201502 - Integration Testing
201502 - Integration Testing201502 - Integration Testing
201502 - Integration Testing
 
201311 - Middleware
201311 - Middleware201311 - Middleware
201311 - Middleware
 
201303 - Golo
201303 - Golo201303 - Golo
201303 - Golo
 
201303 - Java8
201303 - Java8201303 - Java8
201303 - Java8
 
201305 - Lambda by R. Forax
201305 - Lambda by R. Forax201305 - Lambda by R. Forax
201305 - Lambda by R. Forax
 
201301 - Focus Neo4j
201301 - Focus Neo4j201301 - Focus Neo4j
201301 - Focus Neo4j
 
201301 - Panorama NoSQL
201301 - Panorama NoSQL201301 - Panorama NoSQL
201301 - Panorama NoSQL
 
201209 LT Clojure
201209 LT Clojure201209 LT Clojure
201209 LT Clojure
 
Spring Batch Workshop (advanced)
Spring Batch Workshop (advanced)Spring Batch Workshop (advanced)
Spring Batch Workshop (advanced)
 
Spring Batch Workshop
Spring Batch WorkshopSpring Batch Workshop
Spring Batch Workshop
 
Engagement des sociétés d'Ingénierie dans la contribution open source : un ce...
Engagement des sociétés d'Ingénierie dans la contribution open source : un ce...Engagement des sociétés d'Ingénierie dans la contribution open source : un ce...
Engagement des sociétés d'Ingénierie dans la contribution open source : un ce...
 
GlassFish, Application versioning et rolling upgrade en haute disponibilité
GlassFish, Application versioning et rolling upgrade en haute disponibilitéGlassFish, Application versioning et rolling upgrade en haute disponibilité
GlassFish, Application versioning et rolling upgrade en haute disponibilité
 
Développement dans le cloud - Sacha Labourey
Développement dans le cloud - Sacha LaboureyDéveloppement dans le cloud - Sacha Labourey
Développement dans le cloud - Sacha Labourey
 
Présentation Granite ds lyon 2011 par William Draï
Présentation Granite ds lyon 2011 par William DraïPrésentation Granite ds lyon 2011 par William Draï
Présentation Granite ds lyon 2011 par William Draï
 
20091020 JPA2
20091020 JPA220091020 JPA2
20091020 JPA2
 

Dernier

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Dernier (20)

Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 

201209 Lombok & Guava

  • 1. Milou fait un régime Guava - Lombok
  • 3. @thierryleriche Thierry Leriche-Dessirier  Consultant JEE freelance  Professeur de Génie Logiciel à l’ESIEA  Rédacteur pour Programmez  Rédacteur pour Developpez.com icauda.com
  • 4. Cours Forums FAQ News Interviews Critiques Articles / tutoriels Agendas Magazine
  • 5. 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
  • 6.  Milou est trop lourd (intro) Agenda  Lombok (et Lombok-pg) en action  Tour d’horizon de Guava
  • 7. Milou est trop lourd (et doit faire un régime) I am Milou
  • 8. 5 DOG 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 ; ...
  • 9. Constructeurs  Getters / setters  toString ()  equals ()  hashCode ()  compareTo ()  id  name  fullName  sex  birthday  race  lof  weight  size  Colors
  • 10. Constructeurs  Getters / setters  toString ()  equals ()  hashCode ()  compareTo ()  id  name clic clic  fullName démo  sex  birthday  race  lof  weight  size  Colors
  • 11. 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 ?...
  • 12. Constructeurs  Getters / setters  toString ()  equals ()  hashCode ()  compareTo () 10 attributs  210 lignes  id  name  fullName  sex  birthday  race  lof  weight  size  Colors
  • 13. 10 attributs Java 210 lignes de code
  • 14. Va chercher Guava   toString ()  equals ()  hashCode ()  compareTo () Commons  FAQ 1-2
  • 15. Base Objects
  • 16. Java 5 public String toString() { return "Dog [id=" + id + ", name=" + name + ", fullName=" + fullName 5 + ", sex=" + sex + ", birthday=" + birthday + ", race=" + race + ", lof=" + lof + ", weight=" + weight + ", size=" + size + ", colors=" + colors + "]"; } Simple, efficace et bien pourri   toString ()
  • 17. Java 5 public String toString() { StringBuilder sb = new StringBuilder(); sb.append(Dog.class.getSimpleName()) .append("[id=").append(id) 5 .append(", name=").append(name) .append(", fullName=").append(fullName) ... .append(", colors=").append(colors); return sb.toString(); } Mieux mais sans plus   toString ()
  • 18. Guava public String toString() { return Objects.toStringHelper(this) .add("id", id) .add("name", name) G .add("fullName", fullName) ... .add("colors", colors) .toString(); } Builder  toString ()
  • 19. birthday, fullname, name, race et sex Java 5 public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; 5 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; } Carrément illisible   equals ()
  • 20. birthday, fullname, name, race et sex Guava public boolean equals(Object obj) { if (!(obj instanceof Dog)) return false; Dog other = (Dog) obj; G return Objects.equal(birthday, other.birthday) && Objects.equal(fullname, other.fullname) && Objects.equal(name, other.name) && Objects.equal(race, other.race) && sex == other.sex; }  equals ()
  • 21. birthday, fullname, name, race et sex Java 5 public int hashCode() { final int prime = 31; int result = 1; result = prime * result 5 + ((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; }  hashCode ()
  • 22. birthday, fullname, name, race et sex Guava public int hashCode() { } return Objects.hashCode(birthday, fullName, name, race, sex); G  hasCode()
  • 23. name, fullname, birthday, weight, size, race et sex Java 5 public int compareTo(Dog other) { int result = 0; result = name.compareTo(other.name); if (result != 0) { 5 return result; } result = fullname.compareTo(other.fullname); if (result != 0) { return result; } ... }  compareTo ()
  • 24. name.compareTo(other.name) Vsother.name.compareTo(name)  compareTo ()
  • 25. name, fullname, birthday, weight, size, race et sex Guava public int compareTo(Dog other) { return ComparisonChain.start() .compare(name, other.name) .compare(fullName, other.fullName) .compare(birthday, other.birthday) G .compare(weight, other.weight) .compare(size, other.size) .compare(race, other.race) .compare(sex, other.sex) .result(); }  compareTo ()
  • 26. Lombok en action
  • 27. Régime Annotations de base
  • 28. Régime  @NoArgsConstructor / @RequiredArgsConstructor / @AllArgsConstructor  constructeurs  @Getter / @Setter  @ToString  @EqualsAndHashCode  @Data  @Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor
  • 29. Régime  @NoArgsConstructor / @RequiredArgsConstructor / @AllArgsConstructor  @Getter / @Setter  @ToString  @EqualsAndHashCode  @Data clic clic démo
  • 30. 10 attributs Java 210 lignes de code Lombok 12 lignes + 2-3 @ + compareTo()
  • 31. Factory @RequiredArgsConstructor(staticName = "of") public class Dog { private Integer id; @NonNull private String name;  L private String fullName; @NonNull private SexeEnum sex;  private Date birthday; ... name, sex  Dog dog = Dog.of("Milou", MALE);
  • 32. Factory @RequiredArgsConstructor(staticName = "of") public class Dog { private Integer id; @NonNull private String name;  L private String fullName; @NonNull private SexeEnum sex;  private Date birthday; ... name, sex  Dog dog = Dog.of("Milou", MALE); 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); }
  • 33. Trucs pratiques Se simplifier la vie
  • 34. Pratique  @Cleanup  @Synchronized  @SneakyThrows  @Log  @Delegate  val
  • 35. Ressources public void lireJava6(String from) { InputStream in = null; try { in = new FileInputStream(from); byte[] b = new byte[10000]; 5 while (true) { int r = in.read(b); if (r == -1) break; ... } } catch (Exception e) { ... } finally { if (in != null) { try { in.close(); } catch (Exception e) { ... } } ...
  • 36. Ressources public void lire(String from) throws IOException { @Cleanup InputStream in = new FileInputStream(from); byte[] b = new byte[10000]; L while (true) { int r = in.read(b); if (r == -1) break; ... } }
  • 37. Délombok Revenir sans la lib
  • 38. java -jar lombok.jar delombok src -d src-delomboked Délombok <properties> <lombok.sourceDirectory> ${project.basedir}/src/main/java </lombok.sourceDirectory> ... XML <build> <groupId>org.projectlombok</groupId> <artifactId>maven-lombok-plugin</artifactId> <executions> <execution> <phase>generate-sources</phase> </execution> </executions> ... mvn lombok:delombok
  • 39. Délombok @Data public class Dog { 5 5 private Integer id; public class Dog { private String name; private Integer id; private String fullName; private String name; private SexeEnum sex; private String fullName; private Date birthday; ... private String race; private List<String> colors; private Boolean lof; private Double weight; public DogLombok() { private Double size; } private List<String> colors; @java.lang.Override } @java.lang.SuppressWarnings("all") public boolean equals(final java.lang.Obje if (o == this) return true; mvn if (o == null) return false; lombok:delombok if (o.getClass() != this.getClass()) ret final Dog other = (Dog)o; if (this.getId() == null ? other.getId() ... @java.lang.Override @java.lang.SuppressWarnings("all") public int hashCode() { final int PRIME = 31; int result = 1; result = result * PRIME + (this.getId()
  • 40. Lombok-pg Annotations supplémentaires
  • 41. Annotations Pg  @Action  @Builder  @Function  @LazyGetter  @EnumId  @FluentSetter  @Rethrow / @Rethrows  @Predicate  @Singleton  @AutoGenMethodStub  @BoundPropertySupport / @BoundSetter  @DoPrivileged  @ExtensionMethod  @ListenerSupport  @WriteLock / @ReadLock  @Await / @Signal / @AwaitBeforeAndSignalAfter  @Sanitize.Normalize / .With  @SwingInvokeLater / @SwingInvokeAndWait  @Validate.NotEmpty / .NotNull / .With  @VisibleForTesting
  • 42. Fluent @FluentSetter @Getter public class Dog { private Integer id ; L private String name ; private String fullName ; ...  DogLombok dog = new DogLombok(); dog.name("Milou").sex(MALE); println( dog.getName()); //  Milou println( dog.getSex()); //  MALE
  • 43. Builder @Builder @Getter public class Dog { private Integer id ; L private String name ; private String fullName ; ...  Dog dog = Dog.dog().name("Milou").sex(MALE).build(); println( dog.getName()); //  Milou println( dog.getSex()); //  MALE
  • 44. extension @ExtensionMethod({ Dog.class, MyDogExtensionClass.class }) public class DogWithExtension { public void foo() { Dog milou = new Dog("Milou", 12.5, ...); L boolean isTooFat = milou.isTooFat(); } } class MyDogExtensionClass { public static boolean isTooFat(final Dog dog) { double imc = dog.getWeight() / pow(dog.getSize(), 2); return 25 < imc; } } Avec paramètres  FAQ 9  http://blog.developpez.com/todaystip/p11165/dev/java/extensionmethod-de-lombok-pg/
  • 45. Lombok or not Lombok ? Avantages et inconvénients
  • 46. Pro / Cons  Byte code modifié   Version en 0.x  Documentation des prog ?  Magique ?  Compacité  Lecture simplifiée  Code normée  Délombok (pour essayer)
  • 47. Guava tour d’horizon
  • 48. Factory Methods Les choses que j’aime
  • 49. < new Vs static factories > Java 5 List<Integer> primeNumbers = new ArrayList<Integer>(); Set<String> colors = new TreeSet<String>(); 5 Map<String, Integer> ages = new HashMap<String, Integer>();
  • 50. < new Vs static factories > Java 5 List<Integer> primeNumbers = new ArrayList<Integer>(); Set<String> colors = new TreeSet<String>(); Map<String, Integer> ages = new HashMap<String, Integer>(); 5 5 dur dur ? 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 = ...
  • 51. < new Vs static factories > Java 5 List<Integer> primeNumbers = new ArrayList<Integer>(); Set<String> colors = new TreeSet<String>(); Map<String, Integer> ages = new HashMap<String, Integer>(); 5 7 Java 7 List<Integer> primeNumbers = new ArrayList<>(); Set<String> colors = new TreeSet<>(); Map<String, Integer> ages = new HashMap<>(); Qui utilise Java 7 en prod ?
  • 52. < new Vs static factories > Java 5 List<Integer> primeNumbers = new ArrayList<Integer>(); Set<String> colors = new TreeSet<String>(); Map<String, Integer> ages = new HashMap<String, Integer>(); 5 7 Java 7 List<Integer> primeNumbers = new ArrayList<>(); Set<String> colors = new TreeSet<>(); Map<String, Integer> ages = new HashMap<>(); Qui utilise Java 7 en prod ? G Guava List<Integer> primeNumbers = newArrayList(); Set<String> colors = newTreeSet(); Map<String, Integer> ages = newHashMap(); Dès maintenant !
  • 53. < new Vs static factories > Java 5 List<Integer> primeNumbers = new ArrayList<Integer>(); Set<String> colors = new TreeSet<String>(); Map<String, Integer> ages = new HashMap<String, Integer>(); 5 7 Java 7 List<Integer> primeNumbers = new ArrayList<>(); Set<String> colors = new TreeSet<>(); Map<String, Integer> ages = new HashMap<>(); Qui utilise Java 7 en prod ? G Guava List<Integer> primeNumbers = newArrayList(); Set<String> colors = newTreeSet(); Map<String, Integer> ages = newHashMap(); Dès maintenant ! Lombok var primeNumbers = new ArrayList<Integer>(); -> primeNumbers.size(); ... L
  • 54. < new Vs static factories > G List of dogs 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, ...)); [Milou, Rintintin, Volt, Lassie, Pluto, Medor]
  • 55. Immutables Pour que ça ne change pas
  • 57. immutable Quand ? 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.
  • 58. < unmodifiables Vs immutables > Java 5 Set<Integer> temp = new LinkedHashSet<Integer>(Arrays.asList(1, 2, 3, 5, 7)); Set<Integer> primes = Collections.unmodifiableSet(temp);
  • 59. < unmodifiables Vs immutables > Java 5 Set<Integer> temp = new LinkedHashSet<Integer>(Arrays.asList(1, 2, 3, 5, 7)); Set<Integer> primes = Collections.unmodifiableSet(temp); G Guava Set<Integer> primes = ImmutableSet.of(1, 2, 3, 5, 7);
  • 60. < unmodifiables Vs immutables > Of ImmutableSet.of(E ImmutableSet.of(E ImmutableSet.of(E ImmutableSet.of(E ImmutableSet.of(E e1) e1, e1, e1, e1, E E E E e2) e2, e2, e2, E E E e3) e3, E e4) e3, E e4, E e5) G 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  http://blog.developpez.com/guava/p10589/collection/title-212/
  • 61. < Copie de défense > Java 5 public class Dog { private String name; ... private List<String> colors; 5 public Dog(String name, List<String> colors) { this.name = name; ... this.colors = Collections.unmodifiableList( new ArrayList<String>(colors)); } public List<String> getColors() { return colors; }
  • 62. < Copie de défense > Guava public class Dog { private String name; ... private ImmutableList<String> colors; G public Dog(String name, List<String> colors) { this.name = name; ... this.colors = ImmutableList.copyOf(colors); } public ImmutableList<String> getColors() { return colors; } Message clair
  • 63. Collections en plus Multimap, Bipap, Multiset
  • 64. < Multi Map > Java 5 Map<String, List<String>> dogFavoriteColors = new HashMap<String, List<String>>(); 5 } milouColors = new ArrayList<String>(); dogFavoriteColors.put("Milou",milouColors); 5 List<String> milouColors = dogFavoriteColors.get("Milou"); if(milouColors == null) { milouColors.add("Vert");
  • 65. < Multi Map > Java 5 Map<String, List<String>> dogFavoriteColors = new HashMap<String, List<String>>(); 5 } milouColors = new ArrayList<String>(); dogFavoriteColors.put("Milou",milouColors); 5 List<String> milouColors = dogFavoriteColors.get("Milou"); if(milouColors == null) { milouColors.add("Vert"); G Guava Multimap<String, String> dogFavoriteColors = HashMultimap.create(); dogFvoriteColors2.put("Milou", "Jaune"); dogFavoriteColors2.put("Milou", "Rouge");
  • 66. < Bi Map > G Guava BiMap<String, Dog> tatouages = HashBiMap.create(); tatouages.put("ABC123", new Dog("Milou") ); tatouages.put("MBD324", new Dog("Volt") ); tatouages.put("JFT672", new Dog("Lassie") ); println( tatouages ); {ABC123=Milou, MBD324=Volt, ABC123=Milou println( tatouages.inverse() ); Une map bijective JFT672=Lassie} {Milou=ABC123, MDB324=Volt Volt=MBD324, Lassie=JFT672} JFT672=Lassie Il est possible de changer la valeur associée à une clé mais pas d'avoir deux clés avec la même valeur (IllegalArgumentException).
  • 67. < Multi Set > Guava G 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 ); [2, 3 x 2, 5, 7, 11] println( ages.count(3) ) 2
  • 69. toString ()  equals ()  hashCode ()  compareTo ()
  • 70. < Preconditions > DOG public class Dog { private Integer private String private String id ; name ; fullName ; 5 ... 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; ... }
  • 71. < Preconditions > DOG G 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"); ... } checkNotNull()  NPE checkArgument()  IAE checkState()  ISE
  • 72. Joiner String names = Joiner.on(", ") .join(newArrayList("Lassie", "Volt", "Milou")); "Lassie, Volt, Milou" G Java classique 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();
  • 73. Joiner String names = Joiner.on(", ") .join(newArrayList("Lassie", "Volt", "Milou")); "Lassie, Volt, Milou" G String names = Joiner.on(", ") .join(newArrayList("Lassie", "Volt", null, "Milou"));  NPE 
  • 74. Joiner String names = Joiner.on(", ") .join(newArrayList("Lassie", "Volt", "Milou")); "Lassie, Volt, Milou" G String names = Joiner.on(", ") .join(newArrayList("Lassie", "Volt", null, "Milou"));  NPE  String names = Joiner.on(", ") .skipNulls() .join(newArrayList("Lassie", "Volt", null, "Milou")); "Lassie, Volt, Milou" G
  • 75. Joiner String names = Joiner.on(", ") .join(newArrayList("Lassie", "Volt", "Milou")); "Lassie, Volt, Milou" G String names = Joiner.on(", ") .join(newArrayList("Lassie", "Volt", null, "Milou"));  NPE  String names = Joiner.on(", ") .skipNulls() .join(newArrayList("Lassie", "Volt", null, "Milou")); "Lassie, Volt, Milou" G G String names = Joiner.on(", ") .useForNull("Anonymous")) .join(newArrayList("Lassie", "Volt", null, "Milou")); "Lassie, Volt, Anonymous, Milou"  http://blog.developpez.com/guava/p11054/base/joiner-pour-assembler-des-items/
  • 76. Splitter Iterable<String> dogNames = Splitter.on(",") [ "Lassie", .split("Lassie, Volt, Milou"); "Volt", "Milou" ]
  • 77. Splitter Iterable<String> dogNames = Splitter.on(",") [ "Lassie", .split("Lassie, Volt, Milou"); "Volt", "Milou" ] Iterable<String> dogNames = Splitter.on(",") [ "Lassie", .split("Lassie, Volt, ,Milou"); "Volt", " ", "Milou" ]
  • 78. Splitter Iterable<String> dogNames = Splitter.on(",") [ "Lassie", .split("Lassie, Volt, Milou"); "Volt", "Milou" ] Iterable<String> dogNames = Splitter.on(",") [ "Lassie", .split("Lassie, Volt, ,Milou"); "Volt", " ", "Milou" ] Iterable<String> dogNames = Splitter.on(",") [ "Lassie", .trimResults() "Volt", .split("Lassie, Volt, ,Milou"); "", "Milou" ]
  • 79. Splitter Iterable<String> dogNames = Splitter.on(",") [ "Lassie", .split("Lassie, Volt, Milou"); "Volt", "Milou" ] Iterable<String> dogNames = Splitter.on(",") [ "Lassie", .split("Lassie, Volt, ,Milou"); "Volt", " ", "Milou" ] Iterable<String> dogNames = Splitter.on(",") [ "Lassie", .trimResults() "Volt", .split("Lassie, Volt, ,Milou"); "", "Milou" ] Iterable<String> dogNames = Splitter.on(",") .trimResults() .omitEmptyStrings() [ "Lassie", .split("Lassie, Volt, ,Milou"); "Volt", "Milou" ] G  http://blog.developpez.com/guava/p11045/annotation/splitter-pour-separer-des-items/
  • 80. Wrapper Optional <T> Optional Dog dog = new Dog("Milou", ...); Optional<Dog> opt = Optional.of(dog); assertTrue( opt.isPresent() ); assertEquals( "Milou", opt.get().getName() );
  • 81. Wrapper Optional <T> Optional 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
  • 82. Wrapper Optional <T> Optional 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);
  • 83. Wrapper Optional <T> Optional 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() );  http://blog.developpez.com/guava/p11163/base/le-wrapper-optional-de-guava/
  • 86. Super Chien public class SuperChien implements SuperHero { private private private String double Set<String> surnom ; poids ; couleursCostume ; 5 private Set<String> pouvoirs ; ... 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.
  • 87. < Transformation > Transformation List<SuperChien> superChiens = Lists.transform(dogs, @Override new Function<Dog, SuperChien>() { public SuperChien apply(Dog dog) { G 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]
  • 88. < Transformation > Transformation G 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(...
  • 89. < Filtre > Filtre Predicate<Dog> malePredicate = new Predicate<Dog>() { public boolean apply(Dog dog) { } return dog.getSex() == MALE; G } Iterable<Dog> maleDogs = Iterables.filter(dogs, malePredicate); [Milou, Rintintin, G Volt, Pluto, Medor]
  • 90. < Filtre > Filtre Predicate<Dog> malePredicate = new Predicate<Dog>() { public boolean apply(Dog dog) { } return dog.getSex() == MALE; [Milou, G } Rintintin, Volt, Iterable<Dog> maleDogs = Iterables.filter(dogs, malePredicate); Pluto, Medor] G Dog firstMaleDog = Iterables.find(dogs, malePredicate); Milou G
  • 91. < Filtre > Filtre Predicate<Dog> malePredicate = new Predicate<Dog>() { public boolean apply(Dog dog) { } return dog.getSex() == MALE; [Milou, G } Rintintin, Volt, Iterable<Dog> maleDogs = Iterables.filter(dogs, malePredicate); Pluto, Medor] G Dog firstMaleDog = Iterables.find(dogs, malePredicate); Milou G Dog firstMaleDog = Iterables.find(femaleDogs, malePredicate, DEFAULT_DOG ); Default dog
  • 92. G Seconde liste List<Dog> dogs2 = newArrayList( new Dog("Rintintin", 45.0, MALE, ...), new Dog("Pluto", 22.0, MALE, ...), new Dog("Lulu", 35.6, MALE, ...)); [Rintintin, [Milou, Pluto, Rintintin, Lulu] Volt, Liste 2 : dogs2 Lassie, Pluto, Medor] Liste 1 : dogs
  • 93. < Fluent or not fluent ? > Pas fluent Predicate<Dog> malePredicate = new Predicate<Dog>() { public boolean apply(Dog dog) { return dog.getSex() == MALE; }}; G Function<FullDog, String> nameFunction = new Function<FullDog, String>() { public String apply(FullDog dog) { return dog.getName(); }}; G G Iterable<FullDog> maleDogs = Iterables.filter(dogs, malePredicate); Iterable<String> maleNames = Iterables.transform(maleDogs, nameFunction); [Milou, Rintintin, Volt, Pluto, Medor]
  • 94. < Fluent or not fluent ? > Pas fluent Iterable<FullDog> maleDogs = Iterables.filter(dogs, malePredicate); Iterable<String> maleNames = Iterables.transform(maleDogs, nameFunction); G G Fluent List<String> maleNames2 = FluentIterable.from(dogs) .filter(malePredicate) .transform(nameFunction) .toImmutableList(); Guava 12.0 [Milou, Rintintin, Volt, Pluto,  http://blog.developpez.com/guava/p11092/annotation/fluentiterable-sur- Medor] mon-chien-guava/
  • 95. Cache todo
  • 96. < Memoization > Web Service public class DogService { @Inject private PetShopWebService service; public Integer getNumberDogsSoldYesterday() { 5 return service.checkSales( "dog" ); }
  • 97. < Memoization > Web Service public class DogService { @Inject private PetShopWebService service; public Integer getNumberDogsSoldYesterday() { 5 return service.checkSales( "dog" ); } 5 Cache manuel private Integer nbOfDogsSold; public Integer getNumberDogsSoldYesterday() { if (nbOfDogsSold == null) { nbOfDogsSold = service.checkSales( "dog" ); } return nbOfDogsSold; } Double check null…
  • 98. < Memoization > Guava public class DogService { @Inject private PetShopWebService service; private Supplier<Integer> nbOfDogsSoldSupplier = G Suppliers.memoize( new Supplier<Integer>() { public Integer get() { return service.checkSales( "dog" ); } }); public Integer getNumberDogsSoldYesterday() { return nbOfDogsSoldSupplier.get(); }
  • 99. < Memoization > Guava public class DogService { @Inject private PetShopWebService service; private Supplier<Integer> nbOfDogsSoldSupplier = G Suppliers.memoizeWithExpiration( new Supplier<Integer>() { public Integer get() { return service.checkSales( "dog" ); } }, 1, TimeUnit.DAYS ); public Integer getNumberDogsSoldYesterday() { return nbOfDogsSoldSupplier.get(); }
  • 100. < Cache > Web Service public class DogService { @Inject private PetShopWebService service; private Map<String, Dog> dogMap = Maps.newHashMap(); 5 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; } Quid du timeout ? Max ?
  • 101. < Cache > Guava public class DogService { @Inject private PetShopWebService service; private LoadingCache<String, Dog> dogCache = G 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 }
  • 102. Hash Fantôme
  • 103. Hash HashFunction hf = Hashing.md5(); HashCode hc = hf.newHasher() .putInt(123) .putString("Milou") G .hash(); byte[] bytes = hc.asBytes();  md5  Murmur3 128 bits  Murmur3 32 bits  Sha1  Sha256  Sha512  goodFastHash
  • 104. < Is in list ? > Préparation int NB_OF_DOGS = 100000; List<Dog> dogs = newArrayList(); Random rand = new Random(); for (int i = 0; i < NB_OF_DOGS; i++) { 5 Dog dog = new Dog(); dog.setName("abc" + rand.nextInt(999)); ... dogs.add(dog); } 5 contains final Dog milou = new Dog(); milou.setName("Milou"); ... boolean isInList = dogs.contains(milou); false (14 ms) dogs.add(milou); boolean isInList = dogs.contains(milou); true (14 ms)
  • 105. < Is in list ? > Bloom filter Funnel<Dog> dogFunnel = new Funnel<Dog>() { public void funnel(Dogdog, PrimitiveSink sink) { sink.putString(dog.getName()) .putString(dog.getFullName()) .putString(dog.getRace()); G }}; BloomFilter<Dog> bloom = BloomFilter.create(dogFunnel, NB_OF_DOGS, 0.01); for (int i = 0; i < NB_OF_DOGS; i++) { ... bloom.put(dog); boolean isInList = bloom.mightContain(milou); false (0 ms) bloom.put(milou); boolean isInList = bloom.mightContain(milou); Guava 13 true (0 ms)  http://blog.developpez.com/guava/p11149/collection/bloom-filter-de-guava-13/
  • 106. Guava or not Guava ? Avantages et inconvénients
  • 107. Pro / Cons  Ne pas en abuser…  Utile  Bonnes pratiques
  • 108. LIENS @thierryleriche
  • 110. ICAUDA  http://icauda.com  http://icauda.com/articles.html (articles)  http://icauda.com/cours.html (slides) Blog Guava  http://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)
  • 111. MERCI
  • 112. 1. Guava Vs Commons FAQ / Bonus 2. Régime façon Apache 3. Fonctionnal prog Vs boucle for 4. Créer des Maps 5. Charsets 6. Converter Spring 7. Orderings 8. Licences 9. Extension avec valeurs 10. Chrono 11. CharMatcher 12. Impl 13. And, or, in… 14. Partition, limit
  • 113. Guava Vs Commons ? http://tinyurl.com/guava-vs-apache 1
  • 114. Régime : la méthode Commons ? L toString public String toString() { return new ToStringBuilder(this) .append("id", id) .append("name", name) .append("fullName", fullName) ... .append("colors", colors) .toString(); } 2
  • 115. Régime : la méthode Commons ? L equals 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(); } 2
  • 116. Régime : la méthode Commons ? L hashCode public int hashCode() { return new HashCodeBuilder(17, 37) .append(birthday) .append(fullname) .append(name) .append(race) .append(sex) .toHashCode(); } 2
  • 117. Régime : la méthode Commons ? L compareTo 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(); } 2
  • 118. Fonctionnal prog Vs boucle for : quand ? Transformation List<SuperChien> superChiens = newArrayList( Lists.transform(dogs, new Function<Dog, SuperChien>() { @Override public SuperChien apply(Dog dog) { SuperChien chien = new SuperChien(); ... })); } return chien; G Vs List<SuperChien> superChiens = newArrayList(); 3 for(Dog dog : dogs) { SuperChien chien = new SuperChien(); } ... superChiens.add(chien); G http://code.google.com/p/guava-libraries/wiki/FunctionalExplained
  • 119. Créer des Maps public static final ImmutableMap<String, Integer> of AGES = ImmutableMap.of("Milou", 32, G "Volt", 7, "Pluto", 37, "Lassie", 17); public static final ImmutableMap<String, Integer> Builder AGES = new ImmutableMap.Builder<String, Integer>() .put("Milou", 32) .put("Volt", 7) .put("Pluto", 37) .put("Lassie", 17) 4 .put("Medor", 5) .put("Croquette", 8) G .put("Loulou", 2) ... .build();
  • 120. Charsets Java 5 String name = "Milou"; try { byte[] bytes = name.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { 5 throw new AssertionError(e); } Ca n’arrive jamais cette exception  G Guava String name = "Milou"; byte[] bytes = name.getBytes(Charsets.UTF_8); 5
  • 121. Converter Spring G 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 } Lazy or not lazy ?
  • 123. Licences  Lombok : MIT License  Lombok-pg : MIT License  Guava : Apache License 2.0  Commons : Apache License 2.0 8
  • 124. Extension avec valeurs L @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); } 9 } On peut mettre autre chose qu’un "Object", par exemple un "Arrays" , un "Dog" , etc.
  • 125. Extension avec valeurs @ExtensionMethod({ Object.class, MyOtherClass.class }) public class DogWithExtension { public void foo() { String s1 = "toto"; L 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); 9 } public static void print(String value, String other) { if (value == null || value.isEmpty()) { System.out.println(other); } else { System.out.println(value); }
  • 126. < Chrono > long start = new Date().getTime(); Guava Java 5 foo(); // traitement long (ou pas) long end = new Date().getTime(); 5 long duration = end - start; // 11 ms Stopwatch sw = new Stopwatch(); sw.start(); foo(); sw.stop(); G long duration = sw.elapsedMillis(); // 11 ms 10 long nano = sw.elapsedTime(NANOSECONDS); // 11179739 ns long micro = sw.elapsedTime(MICROSECONDS); // 11179 us long millis = sw.elapsedTime(MILLISECONDS); // 11 ms  http://blog.developpez.com/guava/p11160/base/le-stop-watch-de-guava/
  • 128. Impl public class Dog implements Comparable<Dog> { private Integer id ; private String name ; private String fullName ; 5 ... @Override public int compareTo(Dog dog) { return ...; } implements List ? aie aie aie 12
  • 129. Impl @AutoGenMethodStub public class Dog implements Comparable<Dog> { private Integer id ; private String name ; L private String fullName ; ... 12
  • 130. And, or, in… And, or, in... G 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 G import static com.google.common.base.Predicates.or; boolean isTintinInOne = or( in(dogs), in(dogs2) ) .apply(new Dog("Tintin"); false 13 [Milou, Rintintin, Liste 2 : dogs2 Liste 1 : dogs Volt, Lassie, [Rintintin, Pluto, Pluto, Medor] Lulu]
  • 131. Partition, limit Partition List<List<FullDog>> partition = Lists.partition(dogs, 4); [Milou, [Pluto, G Rintintin, Medor] Volt, Lassie] G Limit List<FullDog> first4Dogs = newArrayList(Iterables.limit(dogs, 4)); [Milou, 14 Rintintin, Volt, Lassie]
  • 133. I/O todo
  • 134. < I/O > Ressources public void lireJava6(String from) { InputStream in = null; try { in = new FileInputStream(from); byte[] b = new byte[10000]; 5 while (true) { int r = in.read(b); if (r == -1) break; ... } } catch (Exception e) { ... } finally { if (in != null) { try { in.close(); } catch (Exception e) { ... } } ...
  • 135. < I/O > Java 7 public void lireJava7(String from) { try(InputStream in = new FileInputStream(from)) { ... while (true) { ... 7 } } }
  • 136. < I/O > Guava Todo G
  • 138. Todo