Guava
                    Google Core Libraries for Java 1.5+




 Essential Bytes                  Johannes               1
Agenda




       Was ist Guava?
       Beispiele, Beispiele, Beispiele…




 Essential Bytes               Johannes   2
Was ist Guava?

       Häufig benötigte Klassen & Funktionen die Java „fehlen“
              Hilfsklassen z.B. für Strings, Vergleiche, …
              Neue Datenstrukturen
              Nebenläufigkeit, Multi-Threading
              …
       Ähnlich wie z.B. Apache Commons
       Früher bekannt als Google Collections
       Apache License 2.0
       Sehr aktives Projekt
       GWT-kompatibel
 Essential Bytes                    Johannes                    3
MultiSet

       Auch bekannt als „Bag“
       Wie normales Set,
       aber kann Objekte „mehrfach“ enthalten

Multiset<String> multiset = HashMultiset.create();
multiset.add("Hello World");
multiset.add("Hello World");
System.out.println(multiset.count("Hello World")); //2
multiset.remove("Hello World");
System.out.println(multiset.count("Hello World")); //1

       Selten benötigt, aber dann extrem nützlich


 Essential Bytes               Johannes             4
MultiMap
       Wie normale Map, aber
       kann für jeden Key mehrere Values enthalten
     Person alice = new Person();
     Person bobJr = new Person();
     Person aliceJr = new Person();

     Multimap<Person, Person> parentToChildren =
       HashMultimap.create();
     parentToChildren.put(alice, bobJr);
     parentToChildren.put(alice, aliceJr);

     Collection<Person> aliceChildren =
       parentToChildren.get(alice);

       Ähnlich wie: Map<Person, Collection<Person>>
 Essential Bytes              Johannes               5
BiMap

       Eine Map bei der nicht nur Keys sondern auch Values
       einmalig sind

       Lässt sich deswegen per invert() umdrehen:
       Keys werden zu Values und umgekehrt




 Essential Bytes              Johannes                      6
Table


       Eine Map mit zwei Keys (mehr oder weniger)

              Row-Key

              Column-Key

       Ersatz für Map<T, Map<U, V>>

       Per .row() erhält man eine Map einer Reihe

       Per .column() eine Map einer Spalte




 Essential Bytes               Johannes            7
Collection Utiltities

       Statische Konstruktoren um Collections einfacher
       erzeugen zu können
       Methoden die java.util.Collections fehlen
          .getFirst()
          .frequency()
          …
       Für Listen
          .partition()  Teil Liste in kleinere Listen auf
          .reverse()
          …


 Essential Bytes                Johannes                    8
Collection Utilties

       „Mengenlehre“
         .union()
         .intersection()
         …

       Versionen der java.util.Collections-Methoden für Guava‘s
       neue Datenstrukturen




 Essential Bytes               Johannes                          9
Immutable Collections

       Eine Collection die nicht verändert werden kann
      Collection<String> colors = ImmutableSet.of("red",
        "orange", "yellow", "green", "blue");


       Java kann etwas ähnliches: Unmodifiable Collections
       Collection<String> colors =
         Collections.unmodifiableList(Arrays.asList(
           "red", "orange", "yellow", "green", "blue"));
       Aber
         Original geändert  Unmodifiable Collection geändert
         Keine optimierte Datenstruktur: Speicherverbrauch
         und Performance schlechter als Guava

 Essential Bytes               Johannes                        10
Immutable Collections

Wozu das Ganze?
       Manipulationssicher: Fremder Code kann nicht
       absichtlich oder ausversehen Inhalt ändern
        Methoden sollten wann immer möglich Immutable
       Collections zurückgeben
       Thread-Safe: Keine Änderungen  Keine parallelen
       Änderungen
       Etwas bessere Performance
       Viel besserer Speicherverbrauch (1/3 von HashSet)
       Kann als Konstante verwendet werden



 Essential Bytes              Johannes                    11
equals() und hashCode()
Von Eclipse generiert:
 public class Person {                                    return false;
                                                        if (getClass() != obj.getClass())
    private String firstName;                             return false;
                                                        Person other = (Person) obj;
    private String lastName;                            if (birthDay == null) {
                                                          if (other.birthDay != null)
    private Date birthDay;                                  return false;
                                                        } else if (!birthDay.equals(other.birthDay))
    @Override                                             return false;
    public int hashCode() {                             if (firstName == null) {
      final int prime = 31;                               if (other.firstName != null)
      int result = 1;                                       return false;
      result = prime * result + ((birthDay ==           } else if
        null) ? 0 : birthDay.hashCode());           (!firstName.equals(other.firstName))
      result = prime * result + ((firstName ==            return false;
        null) ? 0 : firstName.hashCode());              if (lastName == null) {
      result = prime * result + ((lastName ==             if (other.lastName != null)
        null) ? 0 : lastName.hashCode());                   return false;
      return result;                                    } else if (!lastName.equals(other.lastName))
    }                                                     return false;
                                                        return true;
    @Override                                         }
    public boolean equals(Object obj) {
      if (this == obj)                              }
        return true;
      if (obj == null)



 Essential Bytes                                Johannes                                          12
equals() und hashCode()
Guava:
 public class Person {
                                                                 Ähnliche
                                                                 Methode gibt
     private String firstName;
                                                                 es auch für
     private String lastName;                                    toString()
     private Date birthDay;

     @Override
     public int hashCode() {
       return Objects.hashCode(firstName, lastName, birthDay);
     }

     @Override
     public boolean equals(Object obj) {
       if (obj instanceof Person) {
         Person other = (Person) obj;
         return Objects.equal(firstName, other.firstName)
             && Objects.equal(lastName, other.lastName)
             && Objects.equal(birthDay, other.birthDay);
       }
       return false;
     }

 }


 Essential Bytes                           Johannes                            13
ComparisonChain
 Java-Standard
  public int compareTo(Person o) {
    if(lastName == null && o.lastName != null)
      return -1;

      int lastNameCompared = lastName.compareTo(o.lastName);
      if(lastNameCompared != 0)
        return lastNameCompared;

      if(firstName == null && o.firstName != null)
        return -1;
      else
        return firstName.compareTo(o.firstName);
  }


  Guava
  public int compareTo(Person o) {
    return ComparisonChain.start().compare(lastName, o.lastName)
        .compare(firstName, o.firstName).result();
  }




 Essential Bytes                      Johannes                    14
Preconditions
Java-Standard
 public void setBirthDay(Date birthDay) {
   Date today = new Date();
   if (today.before(birthDay)) {
    throw new IllegalArgumentException("Birthday must not be in the future");
   }

      this.birthDay = birthDay;                                 Ähnliche
 }                                                              Methoden für:
                                                                • NullPointer
                                                                  Exception
                                                                • IllegalState
  Guava                                                           Exception
                                                                • …
  public void setBirthDay(Date birthDay) {
    Date today = new Date();
    checkArgument(today.before(birthDay), "Birthday must not be in the future");

      this.birthDay = birthDay;
  }



 Essential Bytes                    Johannes                                    15
Joiner
Java-Standard
 Collection<String> animals = Arrays.asList("dog", "cat", "velociraptor");

 String message = "My favorite animals are: ";
 boolean first = true;
 for (String animal : animals) {
   if (first) {
     first = false;
   } else {                                             Kann auch:
     message += ", ";
   }
                                                        • Maps „joinen“
   message += animal;                                   • null auslassen
 }                                                      • null ersetzen
                                                        • uvm.
 System.out.println(message);


  Guava
  Collection<String> animals = Arrays.asList("dog", "cat", "velociraptor");

  System.out.println("My favorite animals are: "
      + Joiner.on(", ").join(animals));

 Essential Bytes                    Johannes                                 16
Splitter




 Essential Bytes   Johannes   17
Splitter

       Das Gegenstück zum Joiner
       Iterable<String> animals =
       Splitter.on(',').split("cat, dog, velociraptor");


       Java kann das zwar auch
       String[] animals =
       "cat, dog, velociraptor".split(",");
       aber
              Verwendet reguläre Ausdrücke (split(".") geht also schief)
              Gibt Arrays zurück
              Seltsamer Umgang mit null-Werten und Leerzeichen




 Essential Bytes                      Johannes                            18
Splitter

"cat,dog, ,         velociraptor        ".split(",");
 „cat“, „dog“, „ “, „ velociraptor „



Splitter.on(',').trimResults().omitEmptyStrings()
  .split("cat,dog, , velociraptor ");
 „cat“, „dog“, „velociraptor“

                                                        Kann auch:
                                                        • Regex
                                                        • null ersetzen
                                                        • Füllzeichen
                                                          ersetzen
                                                        • uvm.



 Essential Bytes                        Johannes                         19
Primitives

       Min / Max
       Longs.min(7823, 23487, 198, 213, 2340);

       Saturated Cast
       int number = (int) 12345678910; //-539222978

       int number = Ints.saturatedCast(12345678910);
       //2147483647


       uvm.




 Essential Bytes            Johannes                  20
Unsigned

       Wrapper- und Utility-Klassen für unsigned int und long
       UnsignedInteger number =
         UnsignedInteger.valueOf(Integer.MAX_VALUE);
       number = number.add(UnsignedInteger.valueOf(1L));
       System.out.println(number); //2147483648




 Essential Bytes               Johannes                        21
common.io

       Bessere Ein- und Ausgabestreams für Dateien
       Methoden wie
         Kopieren
         Verschieben
         …
       Aber:
         durch Java 7 hinfällig
         evtl. für Java 5 & 6 noch interessant




 Essential Bytes             Johannes               22
Optional

Gefährlich: null als „optional“ oder „nicht gefunden“
  Person findPersonBy(Collection<Person> persons,
  String firstName, String lastName) {

        for (Person person : persons) {
          if (firstName.equals(person.getFirstName())
              && lastName.equals(person.getLastName())) {
            return person;
          }
        }

        // No matching entry found, return null
        return null;
  }

 Essential Bytes             Johannes                      23
Optional

Was wenn
    Eine Person nicht gefunden wird und der Aufrufer mit
    dem Null-Wert arbeitet?
    Nach einer Person ohne Vornamen gesucht wird?
 NullPointerException




 Essential Bytes          Johannes                        24
Optional


Optional<Person> findPerson(Collection<Person> persons,
    Optional<String> firstName, String lastName) {

    for (Person person : persons) {
      if ((!firstName.isPresent()
          || firstName.equals(person.getFirstName()))
          && lastName.equals(person.getLastName())) {
        return Optional.of(person);
      }
    }

    // No matching entry found, return absent
    return Optional.absent();
}


 Essential Bytes           Johannes                    25
Optional

       Erzeugen
       Optional.of(reference); //Fehler bei null
       Optional.fromNullable(reference);
       Optional.absent();

       Verwenden
       .isPresent()
       .get()
       .or(defaultValue)
       .orNull()




 Essential Bytes          Johannes                26
Cache

  Einfacher Cache
  Nur lokal und nur im RAM
  Unterstützt Nebenläufigkeit
  „Self populating“
  Aufräumen nach Zeit oder Größe
  Statistiken
 Viel besser als zweckentfremdete Maps
 Kein Ersatz für große Server-Caches (Memcached,
  EHCache, …)



 Essential Bytes        Johannes                   27
Cache

 LoadingCache<String, Person> cache =
   CacheBuilder.newBuilder().maximumSize(500)
   .expireAfterAccess(5, TimeUnit.MINUTES).build(
     new CacheLoader<String, Person>(){
       public Person load(String key) throws Exception{
         return fetchPersonFromDatabase(key);
       }
     }
   );

 Person someone = cache.get("Wulff");




 Essential Bytes         Johannes                   28
EventBus

       Publish-Subscribe-Kommunikation
       Kommunikation zwischen Komponenten
       Komponenten müssen sich nicht kennen
       Vergleichbar mit Observer-Pattern oder Messaging, aber:
         Nur lokal
         Keine Extras wie Persistenz, Vetos, etc.

 Extrem hilfreich, aber Kapitel für sich




 Essential Bytes              Johannes                      29
Und sonst so

       Jede Menge weitere Hilfsmethoden
       Nebenläufigkeit
          Thread-Ersatz für Hintergrunddienste
          Ersatz für ReentrantLock
          Erweiterte Future mit Callback-Unterstützung
       Wert-Bereiche
       „Funktionales Programmieren“ (mit anonymen Klassen)
       Ersatz für hashCode() für Fälle mit zu vielen Kollisionen
       Bloom-Filter
       …


 Essential Bytes                Johannes                          30

Guava - Google Core Libraries for Java 1.5+

  • 1.
    Guava Google Core Libraries for Java 1.5+  Essential Bytes Johannes 1
  • 2.
    Agenda Was ist Guava? Beispiele, Beispiele, Beispiele…  Essential Bytes Johannes 2
  • 3.
    Was ist Guava? Häufig benötigte Klassen & Funktionen die Java „fehlen“ Hilfsklassen z.B. für Strings, Vergleiche, … Neue Datenstrukturen Nebenläufigkeit, Multi-Threading … Ähnlich wie z.B. Apache Commons Früher bekannt als Google Collections Apache License 2.0 Sehr aktives Projekt GWT-kompatibel  Essential Bytes Johannes 3
  • 4.
    MultiSet Auch bekannt als „Bag“ Wie normales Set, aber kann Objekte „mehrfach“ enthalten Multiset<String> multiset = HashMultiset.create(); multiset.add("Hello World"); multiset.add("Hello World"); System.out.println(multiset.count("Hello World")); //2 multiset.remove("Hello World"); System.out.println(multiset.count("Hello World")); //1 Selten benötigt, aber dann extrem nützlich  Essential Bytes Johannes 4
  • 5.
    MultiMap Wie normale Map, aber kann für jeden Key mehrere Values enthalten Person alice = new Person(); Person bobJr = new Person(); Person aliceJr = new Person(); Multimap<Person, Person> parentToChildren = HashMultimap.create(); parentToChildren.put(alice, bobJr); parentToChildren.put(alice, aliceJr); Collection<Person> aliceChildren = parentToChildren.get(alice); Ähnlich wie: Map<Person, Collection<Person>>  Essential Bytes Johannes 5
  • 6.
    BiMap Eine Map bei der nicht nur Keys sondern auch Values einmalig sind Lässt sich deswegen per invert() umdrehen: Keys werden zu Values und umgekehrt  Essential Bytes Johannes 6
  • 7.
    Table Eine Map mit zwei Keys (mehr oder weniger) Row-Key Column-Key Ersatz für Map<T, Map<U, V>> Per .row() erhält man eine Map einer Reihe Per .column() eine Map einer Spalte  Essential Bytes Johannes 7
  • 8.
    Collection Utiltities Statische Konstruktoren um Collections einfacher erzeugen zu können Methoden die java.util.Collections fehlen .getFirst() .frequency() … Für Listen .partition()  Teil Liste in kleinere Listen auf .reverse() …  Essential Bytes Johannes 8
  • 9.
    Collection Utilties „Mengenlehre“ .union() .intersection() … Versionen der java.util.Collections-Methoden für Guava‘s neue Datenstrukturen  Essential Bytes Johannes 9
  • 10.
    Immutable Collections Eine Collection die nicht verändert werden kann Collection<String> colors = ImmutableSet.of("red", "orange", "yellow", "green", "blue"); Java kann etwas ähnliches: Unmodifiable Collections Collection<String> colors = Collections.unmodifiableList(Arrays.asList( "red", "orange", "yellow", "green", "blue")); Aber Original geändert  Unmodifiable Collection geändert Keine optimierte Datenstruktur: Speicherverbrauch und Performance schlechter als Guava  Essential Bytes Johannes 10
  • 11.
    Immutable Collections Wozu dasGanze? Manipulationssicher: Fremder Code kann nicht absichtlich oder ausversehen Inhalt ändern  Methoden sollten wann immer möglich Immutable Collections zurückgeben Thread-Safe: Keine Änderungen  Keine parallelen Änderungen Etwas bessere Performance Viel besserer Speicherverbrauch (1/3 von HashSet) Kann als Konstante verwendet werden  Essential Bytes Johannes 11
  • 12.
    equals() und hashCode() VonEclipse generiert: public class Person { return false; if (getClass() != obj.getClass()) private String firstName; return false; Person other = (Person) obj; private String lastName; if (birthDay == null) { if (other.birthDay != null) private Date birthDay; return false; } else if (!birthDay.equals(other.birthDay)) @Override return false; public int hashCode() { if (firstName == null) { final int prime = 31; if (other.firstName != null) int result = 1; return false; result = prime * result + ((birthDay == } else if null) ? 0 : birthDay.hashCode()); (!firstName.equals(other.firstName)) result = prime * result + ((firstName == return false; null) ? 0 : firstName.hashCode()); if (lastName == null) { result = prime * result + ((lastName == if (other.lastName != null) null) ? 0 : lastName.hashCode()); return false; return result; } else if (!lastName.equals(other.lastName)) } return false; return true; @Override } public boolean equals(Object obj) { if (this == obj) } return true; if (obj == null)  Essential Bytes Johannes 12
  • 13.
    equals() und hashCode() Guava: public class Person { Ähnliche Methode gibt private String firstName; es auch für private String lastName; toString() private Date birthDay; @Override public int hashCode() { return Objects.hashCode(firstName, lastName, birthDay); } @Override public boolean equals(Object obj) { if (obj instanceof Person) { Person other = (Person) obj; return Objects.equal(firstName, other.firstName) && Objects.equal(lastName, other.lastName) && Objects.equal(birthDay, other.birthDay); } return false; } }  Essential Bytes Johannes 13
  • 14.
    ComparisonChain Java-Standard public int compareTo(Person o) { if(lastName == null && o.lastName != null) return -1; int lastNameCompared = lastName.compareTo(o.lastName); if(lastNameCompared != 0) return lastNameCompared; if(firstName == null && o.firstName != null) return -1; else return firstName.compareTo(o.firstName); } Guava public int compareTo(Person o) { return ComparisonChain.start().compare(lastName, o.lastName) .compare(firstName, o.firstName).result(); }  Essential Bytes Johannes 14
  • 15.
    Preconditions Java-Standard public voidsetBirthDay(Date birthDay) { Date today = new Date(); if (today.before(birthDay)) { throw new IllegalArgumentException("Birthday must not be in the future"); } this.birthDay = birthDay; Ähnliche } Methoden für: • NullPointer Exception • IllegalState Guava Exception • … public void setBirthDay(Date birthDay) { Date today = new Date(); checkArgument(today.before(birthDay), "Birthday must not be in the future"); this.birthDay = birthDay; }  Essential Bytes Johannes 15
  • 16.
    Joiner Java-Standard Collection<String> animals= Arrays.asList("dog", "cat", "velociraptor"); String message = "My favorite animals are: "; boolean first = true; for (String animal : animals) { if (first) { first = false; } else { Kann auch: message += ", "; } • Maps „joinen“ message += animal; • null auslassen } • null ersetzen • uvm. System.out.println(message); Guava Collection<String> animals = Arrays.asList("dog", "cat", "velociraptor"); System.out.println("My favorite animals are: " + Joiner.on(", ").join(animals));  Essential Bytes Johannes 16
  • 17.
  • 18.
    Splitter Das Gegenstück zum Joiner Iterable<String> animals = Splitter.on(',').split("cat, dog, velociraptor"); Java kann das zwar auch String[] animals = "cat, dog, velociraptor".split(","); aber Verwendet reguläre Ausdrücke (split(".") geht also schief) Gibt Arrays zurück Seltsamer Umgang mit null-Werten und Leerzeichen  Essential Bytes Johannes 18
  • 19.
    Splitter "cat,dog, , velociraptor ".split(",");  „cat“, „dog“, „ “, „ velociraptor „ Splitter.on(',').trimResults().omitEmptyStrings() .split("cat,dog, , velociraptor ");  „cat“, „dog“, „velociraptor“ Kann auch: • Regex • null ersetzen • Füllzeichen ersetzen • uvm.  Essential Bytes Johannes 19
  • 20.
    Primitives Min / Max Longs.min(7823, 23487, 198, 213, 2340); Saturated Cast int number = (int) 12345678910; //-539222978 int number = Ints.saturatedCast(12345678910); //2147483647 uvm.  Essential Bytes Johannes 20
  • 21.
    Unsigned Wrapper- und Utility-Klassen für unsigned int und long UnsignedInteger number = UnsignedInteger.valueOf(Integer.MAX_VALUE); number = number.add(UnsignedInteger.valueOf(1L)); System.out.println(number); //2147483648  Essential Bytes Johannes 21
  • 22.
    common.io Bessere Ein- und Ausgabestreams für Dateien Methoden wie Kopieren Verschieben … Aber: durch Java 7 hinfällig evtl. für Java 5 & 6 noch interessant  Essential Bytes Johannes 22
  • 23.
    Optional Gefährlich: null als„optional“ oder „nicht gefunden“ Person findPersonBy(Collection<Person> persons, String firstName, String lastName) { for (Person person : persons) { if (firstName.equals(person.getFirstName()) && lastName.equals(person.getLastName())) { return person; } } // No matching entry found, return null return null; }  Essential Bytes Johannes 23
  • 24.
    Optional Was wenn Eine Person nicht gefunden wird und der Aufrufer mit dem Null-Wert arbeitet? Nach einer Person ohne Vornamen gesucht wird?  NullPointerException  Essential Bytes Johannes 24
  • 25.
    Optional Optional<Person> findPerson(Collection<Person> persons, Optional<String> firstName, String lastName) { for (Person person : persons) { if ((!firstName.isPresent() || firstName.equals(person.getFirstName())) && lastName.equals(person.getLastName())) { return Optional.of(person); } } // No matching entry found, return absent return Optional.absent(); }  Essential Bytes Johannes 25
  • 26.
    Optional Erzeugen Optional.of(reference); //Fehler bei null Optional.fromNullable(reference); Optional.absent(); Verwenden .isPresent() .get() .or(defaultValue) .orNull()  Essential Bytes Johannes 26
  • 27.
    Cache EinfacherCache Nur lokal und nur im RAM Unterstützt Nebenläufigkeit „Self populating“ Aufräumen nach Zeit oder Größe Statistiken  Viel besser als zweckentfremdete Maps  Kein Ersatz für große Server-Caches (Memcached, EHCache, …)  Essential Bytes Johannes 27
  • 28.
    Cache LoadingCache<String, Person>cache = CacheBuilder.newBuilder().maximumSize(500) .expireAfterAccess(5, TimeUnit.MINUTES).build( new CacheLoader<String, Person>(){ public Person load(String key) throws Exception{ return fetchPersonFromDatabase(key); } } ); Person someone = cache.get("Wulff");  Essential Bytes Johannes 28
  • 29.
    EventBus Publish-Subscribe-Kommunikation Kommunikation zwischen Komponenten Komponenten müssen sich nicht kennen Vergleichbar mit Observer-Pattern oder Messaging, aber: Nur lokal Keine Extras wie Persistenz, Vetos, etc.  Extrem hilfreich, aber Kapitel für sich  Essential Bytes Johannes 29
  • 30.
    Und sonst so Jede Menge weitere Hilfsmethoden Nebenläufigkeit Thread-Ersatz für Hintergrunddienste Ersatz für ReentrantLock Erweiterte Future mit Callback-Unterstützung Wert-Bereiche „Funktionales Programmieren“ (mit anonymen Klassen) Ersatz für hashCode() für Fälle mit zu vielen Kollisionen Bloom-Filter …  Essential Bytes Johannes 30