Guava’s Collections2: Filtering and Transforming Java Collections

One of the conveniences of Groovy is the ability to easily perform filtering and transformation operations on collections via Groovy’s closure support. Guava brings filtering and transformation on collections to standard Java and that is the subject of this post.

Guava’s Collections2 class features two public methods, both of which are static. The methods filter(Collection, Predicate) and transform(Collection, Function) do what their names imply: perform filtering and transformation respectively on a given collection. The collection to be filtered or transformed is the first parameter to each static method. The filtering function’s second argument is an instance of Guava’s Predicate class. The second argument of the transformation function is an instance of Guava’s Function class. The remainder of this post demonstrates combining all of this together to filter and transform Java collections.

Filtering Collections with Guava

Filtering collections with Guava is fairly straightforward. The following code snippet demonstrates a simple example of this. A Set of Strings is provided (not shown in the code snippet, but obvious in the output that follows the code) and that provided Set is filtered for only entries beginning with a capital ‘J’. This is done via use of Java regular expression support and Guava’s Predicates.containsPattern(String), but there are other types of Predicates that can be specified.

Filtering Strings Beginning with ‘J’
 

   /**
    * Demonstrate Guava's Collections2.filter method. Filter String beginning 
    * with letter 'J'.
    */
   public static void demonstrateFilter()
   {
      printHeader('Collections2.filter(Collection,Predicate): 'J' Languages');
      final Set<String> strings = buildSetStrings();
      out.println('\nOriginal Strings (pre-filter):\n\t' + strings);
      final Collection<String> filteredStrings =
              Collections2.filter(strings, Predicates.containsPattern('^J'));
      out.println('\nFiltered Strings:\n\t' + filteredStrings);
      out.println('\nOriginal Strings (post-filter):\n\t' + strings);
   }

The output from running the above method is shown next. This output shows the lengthy list of programming languages that make up the original Set of Strings returned by buildSetStrings() and shows the results of the filter call featuring only those programming languages that begin with ‘J.’

Transforming Collections with Guava

Transforming collections with Guava works similarly to filtering syntactically, but a Function is used to specify how source collection entries are ‘transformed’ to the output collection rather than using a Predicate to determine which entries to keep. The following code snippet demonstrates transforming entries in a given collection to the uppercase version of themselves.

Transforming Entries to Uppercase
 

   /**
    * Demonstrate Guava's Collections2.transform method. Transform input
    * collection's entries to uppercase form.
    */
   public static void demonstrateTransform()
   {
      printHeader('Collections2.transform(Collection,Function): Uppercase');
      final Set<String> strings = buildSetStrings();
      out.println('\nOriginal Strings (pre-transform):\n\t' + strings);
      final Collection<String> transformedStrings = 
              Collections2.transform(strings, new UpperCaseFunction<String, String>());
      out.println('\nTransformed Strings:\n\t' + transformedStrings);
      out.println('\nOriginal Strings (post-transform):\n\t' + strings);
   }

The above transformation code snippet made use of a class called UpperCaseFunction, but you won’t find that class in the Guava API documentation. That is a custom class defined as shown in the next code listing.

UpperCaseFunction.java
 

package dustin.examples;

import com.google.common.base.Function;

/**
 * Simple Guava Function that converts provided object's toString() representation
 * to upper case.
 * 
 * @author Dustin
 */
public class UpperCaseFunction<F, T> implements Function<F, T>
{
   @Override
   public Object apply(Object f)
   {
      return f.toString().toUpperCase();
   }
}

The output of running the transformation code snippet that uses the UpperCaseFunction class is shown next.

The above code snippets showed methods devoted to filtering and transforming collections’ entries with Guava. The entire code listing for the main class is shown next.

GuavaCollections2.java
 

package dustin.examples;

import static java.lang.System.out;

import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
 * Class whose sole reason for existence is to demonstrate Guava's Collections2
 * class.
 * 
 * @author Dustin
 */
public class GuavaCollections2
{
   /**
    * Provides a Set of Strings.
    * 
    * @return Set of strings representing some programming languages.
    */
   private static Set<String> buildSetStrings()
   {
      final Set<String> strings = new HashSet<String>();
      strings.add('Java');
      strings.add('Groovy');
      strings.add('Jython');
      strings.add('JRuby');
      strings.add('Python');
      strings.add('Ruby');
      strings.add('Perl');
      strings.add('C');
      strings.add('C++');
      strings.add('C#');
      strings.add('Pascal');
      strings.add('Fortran');
      strings.add('Cobol');
      strings.add('Scala');
      strings.add('Clojure');
      strings.add('Basic');
      strings.add('PHP');
      strings.add('Flex/ActionScript');
      strings.add('JOVIAL');
      return strings;
   }

   /**
    * Demonstrate Guava's Collections2.filter method. Filter String beginning 
    * with letter 'J'.
    */
   public static void demonstrateFilter()
   {
      printHeader('Collections2.filter(Collection,Predicate): 'J' Languages');
      final Set<String> strings = buildSetStrings();
      out.println('\nOriginal Strings (pre-filter):\n\t' + strings);
      final Collection<String> filteredStrings =
              Collections2.filter(strings, Predicates.containsPattern('^J'));
      out.println('\nFiltered Strings:\n\t' + filteredStrings);
      out.println('\nOriginal Strings (post-filter):\n\t' + strings);
   }

   /**
    * Demonstrate Guava's Collections2.transform method. Transform input
    * collection's entries to uppercase form.
    */
   public static void demonstrateTransform()
   {
      printHeader('Collections2.transform(Collection,Function): Uppercase');
      final Set<String> strings = buildSetStrings();
      out.println('\nOriginal Strings (pre-transform):\n\t' + strings);
      final Collection<String> transformedStrings = 
              Collections2.transform(strings, new UpperCaseFunction<String, String>());
      out.println('\nTransformed Strings:\n\t' + transformedStrings);
      out.println('\nOriginal Strings (post-transform):\n\t' + strings);
   }

   /**
    * Print a separation header including the provided text.
    * 
    * @param headerText Text to be included in separation header.
    */
   private static void printHeader(final String headerText)
   {
      out.println('\n==========================================================');
      out.println('== ' + headerText);
      out.println('==========================================================');
   }

   /**
    * Main function for demonstrating Guava's Collections2 class.
    * 
    * @param arguments 
    */
   public static void main(final String[] arguments)
   {
      demonstrateFilter();
      demonstrateTransform();
   }
}

Before concluding this post, there is an important caveat to note here. Both methods defined on the Collections2 class contain warnings in their Javadoc documentation about their use. Both methods provide collections that are considered ‘live views’ of the original collections and thus ‘changes to one affect the other.’ For example, removing an element from a source collection similarly removes it from the transformed collection. The documentation for each method also warns that neither returns a collection that is Serializable or thread-safe even when the source collection was Serializable and/or thread-safe.

Conclusion

Guava makes it easier to filter collections and transform collections’ entries in Java. Although the code may not be as concise as that of Groovy for doing similar things, it beats writing straight Java code without use of Guava’s Collections2 class. Java collections can be filtered with Collections2.filter(Collection,Predicate) or transformed with Collections2.transform(Collection,Function).
 

Reference: Filtering and Transforming Java Collections with Guava’s Collections2 from our JCG partner Dustin Marx at the Inspired by Actual Events blog.

Related Whitepaper:

Bulletproof Java Code: A Practical Strategy for Developing Functional, Reliable, and Secure Java Code

Use Java? If you do, you know that Java software can be used to drive application logic of Web services or Web applications. Perhaps you use it for desktop applications? Or, embedded devices? Whatever your use of Java code, functional errors are the enemy!

To combat this enemy, your team might already perform functional testing. Even so, you're taking significant risks if you have not yet implemented a comprehensive team-wide quality management strategy. Such a strategy alleviates reliability, security, and performance problems to ensure that your code is free of functionality errors.Read this article to learn about this simple four-step strategy that is proven to make Java code more reliable, more secure, and easier to maintain.

Get it Now!  

One Response to "Guava’s Collections2: Filtering and Transforming Java Collections"

  1. Yuri NotForPublc says:

    minimum Guava code much useless java code. Conclusion – shity article. There was published much better, much bigger, much detailed article.

Leave a Reply


6 × three =



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books