Google Guava
           Thomas Ferris Nicolaisen
                  @tfnico
              www.tfnico.com

Code at http://github.com/tfnico/guava-examples
So much goodness in here...

• com.google.common.annotation
• com.google.common.base
• com.google.common.collect
• com.google.common.io
• com.google.common.net
• com.google.common.primitives
• com.google.common.util.concurrent
import com.google.common.annotations.*;
/**
 * An annotation that indicates that the visibility of a type or member has
 * been relaxed to make the code testable.
 *
 */
public @interface VisibleForTesting




      /**
       * Use this method for determining that a cart item is eligible for retail
  pickup.
       *
       * @param item with productClass PRINT, or exportName "INDEXPRINT"
       * @return true if it is allowed, false if not
       */
      @VisibleForTesting
      static boolean allowedForRetailPickup(final CartItem item) {
          ...
import com.google.common.base.*;

   @Test
   public void charSetsAndDefaults()
   {
       // Here's some charsets
       Charset utf8 = Charsets.UTF_8;
       assertTrue(utf8.canEncode());

       // Primitive defaults:
       Integer defaultValue = Defaults.defaultValue(int.class);
       assertEquals(0, defaultValue.intValue());
   }
import com.google.common.base.*;

@Test
public void equalityAndIdentity()
{
	 //These could be useful for building equals methods
    assertFalse(Equivalences.equals().equivalent("you", null));
    assertTrue(Equivalences.identity().equivalent("hey", "hey"));
}
import com.google.common.base.*;

 @Test
 public void joinSomeStrings()
 {
     ImmutableSet<String> strings = ImmutableSet.of("A", "B", "C");

     String joined = Joiner.on(":").join(strings);
     assertEquals("A:B:C", joined);
 }
import com.google.common.base.*;
@Test
public void splitSomeStrings()
{
    String string = "A:B:C";

    String[] parts = string.split(":"); //the old way
    String backTogether = Joiner.on(":").join(parts);
    assertEquals(string, backTogether);

    String gorbleString = ": A::: B : C :::";
    Iterable<String> gorbleParts = Splitter.on(":")
       .omitEmptyStrings().trimResults().split(gorbleString);
    String gorbleBackTogether = Joiner.on(":").join(gorbleParts);
    assertEquals(string, gorbleBackTogether); // A:B:C
}
import com.google.common.base.*;
@Test
public void moreFunWithStrings()
{
    assertNull(Strings.emptyToNull(""));
    assertEquals("", Strings.nullToEmpty(null));

    // About the only thing we ever used in commons-lang? :)
     assertTrue(Strings.isNullOrEmpty(""));

    assertEquals("oioioi", Strings.repeat("oi", 3));
    assertEquals("Too short      ", Strings.padEnd("Too short", 15, '
}
//Some customers
Customer bob = new Customer(1, "Bob");
Customer lisa = new Customer(2, "Lisa");
Customer stephen = new Customer(3, "Stephen");
Customer ken = new Customer(null,"Ken");
import com.google.common.base.*;
  @Test
  public void toStringsAndHashcodes()
  {
      Object[] bobAndLisa = new Object[] { bob, lisa };

      // Make some hashcode!
      int hashCode = Objects.hashCode(bob, lisa);

      assertEquals(Arrays.hashCode(bobAndLisa), hashCode);

      // Build toString method
      String string = Objects.toStringHelper(bob)
              .add("name", bob.getName())
              .add("id", bob.getId()).toString();
      assertEquals("Customer{name=Bob, id=1}", string);
  }
import com.google.common.base.*;

 @Test(expected = NullPointerException.class)
 public void needAnIntegerWhichIsNeverNull()
 {
   Integer defaultId = null;
   Integer kensId = ken.getId() != null ? ken.getId() : defaultId;
      // this one does not throw!

     int kensId2 = Objects.firstNonNull(ken.getId(), defaultId);
     assertEquals(0, kensId2);
     // But the above does!
 }
import com.google.common.base.*;


@Test(expected = IllegalArgumentException.class)
public void somePreconditions()
{
    // Pretend this is a constructor:
    Preconditions.checkNotNull(lisa.getId()); // Will throw NPE
    Preconditions.checkState(!lisa.isSick()); // Will throw ILE
    Preconditions.checkArgument(lisa.getAddress() != null,
        "No description for customer with id %s",lisa.getId());
}
import com.google.common.base.*;
 @Test
 public void fancierFunctions()
 {
     Function<Customer, Boolean> isCustomerWithOddId
     = new Function<Customer, Boolean>()
        {
         public Boolean apply(Customer customer)
        {
             return customer.getId().intValue() % 2 != 0;
         }
     };

     assertTrue(isCustomerWithOddId.apply(bob));
     assertFalse(isCustomerWithOddId.apply(lisa));

     // Functions are great for higher-order functions, like
     // project/transform, and fold
 }
import com.google.common.base.*;

@Test
public void somePredicates()
{
    ImmutableSet<Customer> customers =
      ImmutableSet.of(bob, lisa, stephen);

    Predicate<Customer> itsBob = Predicates.equalTo(bob);
    Predicate<Customer> itsLisa = Predicates.equalTo(lisa);
    Predicate<Customer> bobOrLisa = Predicates.or(itsBob, itsLisa);

// Predicates are great to pass in to higher-order functions
// like filter/search
    Iterable<Customer> filtered = Iterables.filter(customers, bobOrLisa
    assertEquals(2, ImmutableSet.copyOf(filtered).size());
}
import com.google.common.base.*;
 @Test
public void someSuppliers()
 {
 	 //Imagine we have Supploer that produces ingredients
 	 IngredientsFactory ingredientsFactory = new IngredientsFactory();
	 	
	 //A function 'bake' - (see next slide)
	 bake();
	
	 //Then it's pretty easy to get a Factory that bakes cakes :)
	 Supplier<Cake> cakeFactory =
       Suppliers.compose(bake(), ingredientsFactory);
	 cakeFactory.get();
	 cakeFactory.get();
	 cakeFactory.get();
	
	 assertEquals(3, ingredientsFactory.getNumberOfIngredientsUsed());
}
import com.google.common.base.*;


 	   private Function<Ingredients, Cake> bake() {
 	   	 return new Function<Ingredients, Cake>() {
 	   	 	 public Cake apply(Ingredients ingredients) {
 	   	 	 	 return new Cake(ingredients);
 	   	 	 }
 	   	 };
 	   }
import com.google.common.base.*;
@Test
public void someThrowables()
{
	
try
	
{
	
	    try{
	
	    	    Integer.parseInt("abc");
	
	    }
	
	    catch(RuntimeException e){
	
	    	    if(e instanceof ClassCastException) throw e; //old-style
	
	    	    Throwables.propagateIfInstanceOf(e, NumberFormatException.class); //the same
	
	    	    Throwables.propagateIfPossible(e); // Propagates if it is Error or RuntimeException
	
	    	    try {
	    	    	   	    Throwables.throwCause(e, true);
	    	    	   } catch (Exception e1) {
	    	    	   	    Throwables.propagate(e1); //Wraps if its a checked exception,
                                             //or lets it flow if not
	    	    	   }
	
	    }
	
}
	
catch(RuntimeException e){
	
	    Throwables.getCausalChain(e);
	
	    Throwables.getRootCause(e);
	
	    Throwables.getStackTraceAsString(e);
	
}
import com.google.common.base.*;
     @Test
	   public void someEnums()
     {
     	 assertEquals("UNDER_DOG",
           CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE,
                  "underDog"));
     	
     	 //Controlling services
     	 Service service = new FunkyService();
     	 service.start();
     	 assertEquals(Service.State.RUNNING, service.state());
        service.stop();
	   }
import com.google.common.collect.*;


@Test
public void someSets()
{
	 ImmutableSet<Customer> customers1 =
       ImmutableSet.of(bob, lisa, stephen);
	 ImmutableSet<Customer> customers2 =
        ImmutableSet.of(stephen, ken);
	
	 assertEquals(4, Sets.union(customers1, customers2).size());
	
	 assertEquals(ImmutableSet.of(stephen),
      Sets.intersection(customers1, customers2));
}
import com.google.common.collect.*;

@Test(expected=NullPointerException.class)
public void someConstraints()
{
    //instead of new HashSet<Customer>()
	 HashSet<Customer> customers = Sets.newHashSet();
	 customers.add(null); //this works. But should it?
	
	 Set<Customer> noMoreNulls =
       Constraints.constrainedSet(customers, Constraints.notNull());
	 noMoreNulls.add(null); //boom!
}
import com.google.common.io.*;

	   @Test
	   public void messAroundWithFile()
	   {
	   	   File file = new File("woop.txt");
	   	   try {
	   	   	    Files.touch(file);
	   	   	
	   	   	    Files.write("Hey sailor!", file, Charsets.UTF_8);
	   	   	
	   	   	    //Breakpoint here.. have a look at the file..
	   	   	
	   	   	    Files.toByteArray(file);
	   	   	    Files.newInputStreamSupplier(file);
	   	   	    assertEquals("Hey sailor!", Files.readFirstLine(file, Charsets.UTF_8));
	   	   	    assertEquals("Hey sailor!", Files.toString(file, Charsets.UTF_8));
	   	
	   	   	    Files.deleteRecursively(file);
	   	   	
	   	   } catch (IOException e) {
	   	   	    Throwables.propagate(e);
	   	   }
	   }
import com.google.common.io.*;


@Test
public void closingAndFlushing()
{
	 InputStream inputStream = System.in;
	 try {
	 	 inputStream.close();//The old way
	 } catch (IOException e) {
	 	 Throwables.propagate(e);
	 }
	 Closeables.closeQuietly(inputStream ); //The new way
	
	 //Or flush:
	 PrintStream outputStream = System.out;
	 Flushables.flushQuietly(outputStream);
}
import com.google.common.io.*;


@Test
public void classPathResources()
{
	 //This:
	 Resources.getResource("com/tfnico/examples/guava/BaseTest.class");
	
	 //instead of this:
	 String location = "com/tfnico/examples/guava/BaseTest.class";
   URL resource2 =
          this.getClass().getClassLoader().getResource(location);
	 Preconditions.checkArgument(resource2!=null,
        "resource %s not found", location);
}
import com.google.common.net.InetAddresses;

	    @Test
	    public void iNetAddressIsFixed()
	    {
	    	   try {
	    	   	
	    	   	    /**
	    	   	     * Unlike InetAddress.getByName(),
	    	   	     * the methods of this class never cause DNS services to be accessed.
	    	   	     * For this reason, you should prefer these methods as much as possible
	    	   	     * over their JDK equivalents whenever you are expecting to handle only
	    	   	     * IP address string literals -- there is no blocking DNS penalty for
	    	   	     * a malformed string.
	    	   	     */
	    	   	    InetAddresses.forString("0.0.0.0");
	    	   	
	    	   	    //Instead of this...
	    	   	    InetAddress.getByName("0.0.0.0");
	    	   	
	    	   } catch (UnknownHostException e) {
	    	   	    Throwables.propagate(e);
	    	   }
	    }
TODO
              (For this presentation)
•   Show off primitives

•   Show off CharMatcher

•   Add more collection examples

•   Add more higher order functions

•   Do concurrency stuff

•   Do cooler io stuff

•   Find patterns of old code that can be replaced
When to think Guava?

• For loops
• Temporary collections
• Mutable collections
• if( x == null)
• In short: method complexity
Arright, let’s try!

Google guava

  • 1.
    Google Guava Thomas Ferris Nicolaisen @tfnico www.tfnico.com Code at http://github.com/tfnico/guava-examples
  • 2.
    So much goodnessin here... • com.google.common.annotation • com.google.common.base • com.google.common.collect • com.google.common.io • com.google.common.net • com.google.common.primitives • com.google.common.util.concurrent
  • 3.
    import com.google.common.annotations.*; /** *An annotation that indicates that the visibility of a type or member has * been relaxed to make the code testable. * */ public @interface VisibleForTesting /** * Use this method for determining that a cart item is eligible for retail pickup. * * @param item with productClass PRINT, or exportName "INDEXPRINT" * @return true if it is allowed, false if not */ @VisibleForTesting static boolean allowedForRetailPickup(final CartItem item) { ...
  • 4.
    import com.google.common.base.*; @Test public void charSetsAndDefaults() { // Here's some charsets Charset utf8 = Charsets.UTF_8; assertTrue(utf8.canEncode()); // Primitive defaults: Integer defaultValue = Defaults.defaultValue(int.class); assertEquals(0, defaultValue.intValue()); }
  • 5.
    import com.google.common.base.*; @Test public voidequalityAndIdentity() { //These could be useful for building equals methods assertFalse(Equivalences.equals().equivalent("you", null)); assertTrue(Equivalences.identity().equivalent("hey", "hey")); }
  • 6.
    import com.google.common.base.*; @Test public void joinSomeStrings() { ImmutableSet<String> strings = ImmutableSet.of("A", "B", "C"); String joined = Joiner.on(":").join(strings); assertEquals("A:B:C", joined); }
  • 7.
    import com.google.common.base.*; @Test public voidsplitSomeStrings() { String string = "A:B:C"; String[] parts = string.split(":"); //the old way String backTogether = Joiner.on(":").join(parts); assertEquals(string, backTogether); String gorbleString = ": A::: B : C :::"; Iterable<String> gorbleParts = Splitter.on(":") .omitEmptyStrings().trimResults().split(gorbleString); String gorbleBackTogether = Joiner.on(":").join(gorbleParts); assertEquals(string, gorbleBackTogether); // A:B:C }
  • 8.
    import com.google.common.base.*; @Test public voidmoreFunWithStrings() { assertNull(Strings.emptyToNull("")); assertEquals("", Strings.nullToEmpty(null)); // About the only thing we ever used in commons-lang? :) assertTrue(Strings.isNullOrEmpty("")); assertEquals("oioioi", Strings.repeat("oi", 3)); assertEquals("Too short ", Strings.padEnd("Too short", 15, ' }
  • 9.
    //Some customers Customer bob= new Customer(1, "Bob"); Customer lisa = new Customer(2, "Lisa"); Customer stephen = new Customer(3, "Stephen"); Customer ken = new Customer(null,"Ken");
  • 10.
    import com.google.common.base.*; @Test public void toStringsAndHashcodes() { Object[] bobAndLisa = new Object[] { bob, lisa }; // Make some hashcode! int hashCode = Objects.hashCode(bob, lisa); assertEquals(Arrays.hashCode(bobAndLisa), hashCode); // Build toString method String string = Objects.toStringHelper(bob) .add("name", bob.getName()) .add("id", bob.getId()).toString(); assertEquals("Customer{name=Bob, id=1}", string); }
  • 11.
    import com.google.common.base.*; @Test(expected= NullPointerException.class) public void needAnIntegerWhichIsNeverNull() { Integer defaultId = null; Integer kensId = ken.getId() != null ? ken.getId() : defaultId; // this one does not throw! int kensId2 = Objects.firstNonNull(ken.getId(), defaultId); assertEquals(0, kensId2); // But the above does! }
  • 12.
    import com.google.common.base.*; @Test(expected =IllegalArgumentException.class) public void somePreconditions() { // Pretend this is a constructor: Preconditions.checkNotNull(lisa.getId()); // Will throw NPE Preconditions.checkState(!lisa.isSick()); // Will throw ILE Preconditions.checkArgument(lisa.getAddress() != null, "No description for customer with id %s",lisa.getId()); }
  • 13.
    import com.google.common.base.*; @Test public void fancierFunctions() { Function<Customer, Boolean> isCustomerWithOddId = new Function<Customer, Boolean>() { public Boolean apply(Customer customer) { return customer.getId().intValue() % 2 != 0; } }; assertTrue(isCustomerWithOddId.apply(bob)); assertFalse(isCustomerWithOddId.apply(lisa)); // Functions are great for higher-order functions, like // project/transform, and fold }
  • 14.
    import com.google.common.base.*; @Test public voidsomePredicates() { ImmutableSet<Customer> customers = ImmutableSet.of(bob, lisa, stephen); Predicate<Customer> itsBob = Predicates.equalTo(bob); Predicate<Customer> itsLisa = Predicates.equalTo(lisa); Predicate<Customer> bobOrLisa = Predicates.or(itsBob, itsLisa); // Predicates are great to pass in to higher-order functions // like filter/search Iterable<Customer> filtered = Iterables.filter(customers, bobOrLisa assertEquals(2, ImmutableSet.copyOf(filtered).size()); }
  • 15.
    import com.google.common.base.*; @Test publicvoid someSuppliers() { //Imagine we have Supploer that produces ingredients IngredientsFactory ingredientsFactory = new IngredientsFactory(); //A function 'bake' - (see next slide) bake(); //Then it's pretty easy to get a Factory that bakes cakes :) Supplier<Cake> cakeFactory = Suppliers.compose(bake(), ingredientsFactory); cakeFactory.get(); cakeFactory.get(); cakeFactory.get(); assertEquals(3, ingredientsFactory.getNumberOfIngredientsUsed()); }
  • 16.
    import com.google.common.base.*; private Function<Ingredients, Cake> bake() { return new Function<Ingredients, Cake>() { public Cake apply(Ingredients ingredients) { return new Cake(ingredients); } }; }
  • 17.
    import com.google.common.base.*; @Test public voidsomeThrowables() { try { try{ Integer.parseInt("abc"); } catch(RuntimeException e){ if(e instanceof ClassCastException) throw e; //old-style Throwables.propagateIfInstanceOf(e, NumberFormatException.class); //the same Throwables.propagateIfPossible(e); // Propagates if it is Error or RuntimeException try { Throwables.throwCause(e, true); } catch (Exception e1) { Throwables.propagate(e1); //Wraps if its a checked exception, //or lets it flow if not } } } catch(RuntimeException e){ Throwables.getCausalChain(e); Throwables.getRootCause(e); Throwables.getStackTraceAsString(e); }
  • 18.
    import com.google.common.base.*; @Test public void someEnums() { assertEquals("UNDER_DOG", CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, "underDog")); //Controlling services Service service = new FunkyService(); service.start(); assertEquals(Service.State.RUNNING, service.state()); service.stop(); }
  • 19.
    import com.google.common.collect.*; @Test public voidsomeSets() { ImmutableSet<Customer> customers1 = ImmutableSet.of(bob, lisa, stephen); ImmutableSet<Customer> customers2 = ImmutableSet.of(stephen, ken); assertEquals(4, Sets.union(customers1, customers2).size()); assertEquals(ImmutableSet.of(stephen), Sets.intersection(customers1, customers2)); }
  • 20.
    import com.google.common.collect.*; @Test(expected=NullPointerException.class) public voidsomeConstraints() { //instead of new HashSet<Customer>() HashSet<Customer> customers = Sets.newHashSet(); customers.add(null); //this works. But should it? Set<Customer> noMoreNulls = Constraints.constrainedSet(customers, Constraints.notNull()); noMoreNulls.add(null); //boom! }
  • 21.
    import com.google.common.io.*; @Test public void messAroundWithFile() { File file = new File("woop.txt"); try { Files.touch(file); Files.write("Hey sailor!", file, Charsets.UTF_8); //Breakpoint here.. have a look at the file.. Files.toByteArray(file); Files.newInputStreamSupplier(file); assertEquals("Hey sailor!", Files.readFirstLine(file, Charsets.UTF_8)); assertEquals("Hey sailor!", Files.toString(file, Charsets.UTF_8)); Files.deleteRecursively(file); } catch (IOException e) { Throwables.propagate(e); } }
  • 22.
    import com.google.common.io.*; @Test public voidclosingAndFlushing() { InputStream inputStream = System.in; try { inputStream.close();//The old way } catch (IOException e) { Throwables.propagate(e); } Closeables.closeQuietly(inputStream ); //The new way //Or flush: PrintStream outputStream = System.out; Flushables.flushQuietly(outputStream); }
  • 23.
    import com.google.common.io.*; @Test public voidclassPathResources() { //This: Resources.getResource("com/tfnico/examples/guava/BaseTest.class"); //instead of this: String location = "com/tfnico/examples/guava/BaseTest.class"; URL resource2 = this.getClass().getClassLoader().getResource(location); Preconditions.checkArgument(resource2!=null, "resource %s not found", location); }
  • 24.
    import com.google.common.net.InetAddresses; @Test public void iNetAddressIsFixed() { try { /** * Unlike InetAddress.getByName(), * the methods of this class never cause DNS services to be accessed. * For this reason, you should prefer these methods as much as possible * over their JDK equivalents whenever you are expecting to handle only * IP address string literals -- there is no blocking DNS penalty for * a malformed string. */ InetAddresses.forString("0.0.0.0"); //Instead of this... InetAddress.getByName("0.0.0.0"); } catch (UnknownHostException e) { Throwables.propagate(e); } }
  • 25.
    TODO (For this presentation) • Show off primitives • Show off CharMatcher • Add more collection examples • Add more higher order functions • Do concurrency stuff • Do cooler io stuff • Find patterns of old code that can be replaced
  • 26.
    When to thinkGuava? • For loops • Temporary collections • Mutable collections • if( x == null) • In short: method complexity
  • 27.