You need to perform logic that is predicated on a certain condition being satisfied, and you want to encapsulate this condition in an object.
Use a Predicate
to evaluate a
criteria or a condition. A Predicate
is an object that evaluates another object and returns true
or false
; predicates are used throughout the
Commons Collections packages for filtering, selecting, and validating
the contents of collections. This code demonstrates the use of simple
predicates to test the type and contents of an object:
import org.apache.commons.collection.Predicate; import org.apache.commons.collection.functors.*; String name = "Tim"; Predicate nameJohn = new EqualPredicate( "John" ); Predicate nameTim = new EqualPredicate( "Tim" ); Predicate instanceString = new InstanceofPredicate( String.class ); Predicate instanceDouble = new InstanceofPredicate( Double.class ); // Testing all predicates for "Tim" System.out.println( "Is Name John?: " + nameJohn.evaluate( name ) ); System.out.println( "Is Name Tim?: " + nameTim.evaluate( name ) ); System.out.println( "Is this a String?: " + instanceString.evaluate( name ) ); System.out.println( "Is this a Double?: " + instanceDouble.evaluate( name ) );
The previous example tests the name
object against a few Predicate
implementations producing the
following console output:
Is Name John?: false Is Name Tim?: true Is this a String?: true Is this a Double?: false
The string "Tim" is subjected to various Predicate
tests. The first two EqualPredicate
objects test the contents of
the string, returning true
if the
object being evaluated is equal to the object passed into the EqualPredicate
's constructor. The last two
Predicate
objects are InstanceofPredicate
instances, which test the
type of object being evaluated; if an InstanceofPredicate
constructor is passed to
the String
class, it returns true
if the object being evaluated is a
java.lang.String
type.
The simple Predicate
interface
is central to a number of utilities introduced in this chapter. To
implement Predicate
, define an
evaluate()
method that returns a
boolean
; a Predicate
is a function object (or functor)
that captures a criteria in an object that can be created and altered at
runtime. Creating and evaluating a Predicate
is just as valid as writing an
if
statement; for example, the code
in the Solution of this recipe could have been implemented as a series
of if
statements:
String name = "Tim"; if( name.equals( "John" ) ) { System.out.println( "The name is John." ); } if( name.equals( "Tim" ) ) { System.out.println( "The name is Tim." ); } if( name instanceof String ) ) { System.out.println( "name is as String object" ); } if( name instanceof Double ) ) { System.out.println( "name is as Double object" ); }
Predicate
instances capture an
if
statement in an object, and if you
are going to constantly change the behavior of your application, you
might want to consider placing conditional expressions in Predicate
instances. For example, if a system
is designed to classify a storm as being a hurricane, you may want to
capture all of your classification criteria in an XML file—parsing this
file at runtime and creating a series of Predicate
objects. A storm is a hurricane when
the winds exceed a certain value, and the barometric pressure falls
below a certain point. But, in a few years those criteria might change
to involve a new, or more complex, set of measurements. If your decision
logic is encapsulated in a Predicate
object, it will be easier to upgrade the program to take new criteria
into account; all of this logic will be encapsulated in an instance of
Predicate
.
Commons Collections provides a number of basic predicates for
common situations, such as testing to see if an object equals another
object (EqualPredicate
), or that an
object is of a certain type (InstanceofPredicate
). Table 4-1 lists a number of simple
Predicate
implementations.
Table 4-1. Predicate implementations
Name |
Description |
---|---|
|
Compares each object to an object passed via a constructor—returning true if the two are equal. |
|
Returns true if the object being evaluated is the
same object reference as the object passed to its constructor.
The |
|
Wraps a |
|
Returns |
|
Returns true if the object being evaluated is
|
|
Returns true if the object being evaluated is not
|
|
Always returns |
|
Always returns |
|
Returns |
The following example demonstrates simple Predicate
objects with
a test for equality, inequality, and equality by identity:
import org.apache.commons.collections.Predicate; import org.apache.commons.collections.functors.*; ... String testName = "Ben"; Predicate equals = new EqualPredicate( testName ); Predicate notEquals = new NotPredicate( equals ); Predicate identity = new IdentityPredicate( testName ); System.out.println( "Does name equal 'Ben'? " + equals.evaluate( "Ben" ) ); System.out.println( "Is object 'Ben'? " + identity.evaluate( testName ) ); System.out.println( "Does name equal 'Tim'? " + equals.evaluate( "Tim" ) ); System.out.println( "Does name not equal 'Tim'? " + notEquals. evaluate( "Tim" ) ); System.out.println( "Is object 'Tim'? " + identity.evaluate( "Tim" ) );
This code demonstrates the use of Predicate
objects to determine if objects are
equal or if two object references reference the same instance. When
executed, the following is output to the console:
Does name equal 'Ben'? true Is object 'Ben'? true Does name equal 'Tim'? false Does name not equal 'Tim'? true Is object 'Tim'? false
The following code demonstrates simple predicates that test for
the presence or absence of null
or if
an object being evaluated is of a certain type. The example also
demonstrates the use of a UniquePredicate
that returns true
when it encounters an object for the
first time:
import org.apache.commons.collections.Predicate; import org.apache.commons.collections.functors.*; String nullString = null; Double testDouble = new Double(3.4); Predicate isString = new InstanceofPredicate( String.class ); Predicate isLong = new InstanceofPredicate( Long.class ); Predicate isNumber = new InstanceofPredicate( Number.class ); Predicate isNotNull = NotNullPredicate.INSTANCE; Predicate isNull = NullPredicate.INSTANCE; Predicate unique = new UniquePredicate( ); System.out.println("'nullString' not null?: " + isNotNull. evaluate(nullString)); System.out.println("'nullString' null?: " + isNull.evaluate(nullString)); System.out.println("'testDouble' a String?: " + isString. evaluate(testDouble)); System.out.println("'testDouble' a Long?: " + isLong.evaluate(testDouble)); System.out.println("'testDouble' a Number?: " + isNumber. evaluate(testDouble)); System.out.println("'A' Unique?: " + unique.evaluate("A")); System.out.println("'C' Unique?: " + unique.evaluate("C")); System.out.println("'A' Unique?: " + unique.evaluate("A")); System.out.println("'B' Unique?: " + unique.evaluate("B"));
The sample evaluates objects against the InstanceofPredicate
, the NullPredicate
, the NotNullPredicate
, and the UniquePredicate
, and the following is output
to the console:
'nullString' not null?: false 'nullString' null?: true 'testDouble' a String?: false 'testDouble' a Long?: false 'testDouble' a Number?: true 'A' Unique?: true 'C' Unique?: true 'A' Unique?: false 'B' Unique?: true
The UniquePredicate
returns
false
the second time it encounters
"A." The Double
object testDouble
is shown to be a Number
object, and the nullString
is evaluated as non-null
.
This recipe mentions function pointers in C and C++. Function pointers are pointers to the address of a function, and they allow for some interesting logical acrobatics. For more information about function pointers in C and C++, see http://www.function-pointer.org/.
Predicate
, Closure
, and Transformer
are all functor objects that are
used throughout the Commons Collections component. You may be familiar
with functors if you have used the Standard Template Library (STL) in
C++. STL documentation contains rigorous definitions for function
objects and
predicates. For more information about functors in STL, see http://www.sgi.com/tech/stl/functors.html.