Featured Post

Applying Email Validation to a JavaFX TextField Using Binding

This example uses the same controller as in a previous post but adds a use case to support email validation.  A Commons Validator object is ...

Thursday, May 19, 2011

Java Collection Shorthand with Closures

For a shorthand technique to checking a Java Collection for an element or counting a number of instances, use the Commons Lang CollectionUtils class.


It's easy to look for an item in a Java Collection or to count the number of instance.  Loop over the Collection, test for a condition, and either return "true" or return a running sum.  For simple testing conditions, say testing two strings for equality, a standard method like contains() may be all you need.

The CollectionUtils class from the Apache Commons Lang library lets you write these type of code blocks in a way that generalizes the testing condition: with closures.  A closure is a function plus its environment.  Closures are very common in the Javascript world and will be added to the Java language in JDK 8.

CollectionUtils allows you to define a Predicate or a testing condition.  This helps when the test for testing isn't readily available in a hashCode() or an equals() method.  Two Strings can be tested easily with an equals() call.  Two Objects -- with String members -- are more difficult to test because of the need to access the fields.  Testing is even more complicated if several fields are compared or the fields need to be compared against variables in the enclosing code block.


This is a sample program that uses two CollectionUtils methods.  First a list is defined.

class MyClass {

   public String data;

   public MyClass(String _data) { data = _data; }
}

public class CountTest {

   public static void main(String[] args) {


    MyClass obj1 = new MyClass("object 1");

    MyClass obj2 = new MyClass("object 1");
    MyClass obj3 = new MyClass("object 2");

    List objList = new ArrayList();
    objList.add(obj1);
    objList.add(obj2);
    objList.add(obj3);

Then a call is made to count the number of "object 2" instanances.  Notice that the key "object 2" is provided as a final variable.  The keyword 'final' must be used.

final String key = "object 1";

System.out.println("matches=" +
    CollectionUtils.countMatches(objList, new Predicate() {
      public boolean evaluate(Object _obj) {
        return key.equals( ((MyClass)_obj).data );
        }
      })
    );

The exists() method can be called in the same way.  This tests against a String constant rather than a final variable.

System.out.println("exists=" +
    CollectionUtils.exists(objList, new Predicate() {
    public boolean evaluate(Object _obj) {
      return "object 3".equals( ((MyClass)_obj).data);
      }
    })
);


The CollectionUtils closures promote reuse by allowing different Predicate implementations to be swapped in.  There are several ones available (NotNullPredicate) as well as a composable solution that will allow several to be logically linked in the JAR.  You'll use your own if the items your testing ("MyClass") aren't fully outfitted with equals() or hashCode() methods.

Here is a link for the Commons Lang JAR files.

http://commons.apache.org/lang/download_lang.cgi

The following is a link to the CollectionUtils Javadoc.

http://commons.apache.org/collections/api-release/index.html

Here are the imports used in the blog post

import java.util.ArrayList;
import java.util.List;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;


No comments:

Post a Comment