Functors- one that performs an operation or a function
- an object that encapsulates some functional logic
eg - Comparator and Iterator
why ?
code reuse
cleaner design --> abstraction
Functor interfaces available in commons:
Predicate - evaluate criteria or conditions and returns a boolean
Transformer - create a new object depending upon the input object
Factory - Create objects
Closure - act on input objects.
Using PredicatesFilterIteratorNon destructive filtering. Basically you set up a filtering condition using a Predicate Object and just pass it to the FilterIterator and the iterator returns only those objects for which the predicate evalutes to a true.
public void testFilterIterator() {
ArrayList list = new ArrayList();
list.add("Hello");
list.add("Hello1");
list.add("Hello2");
FilterIterator filterIterator = new FilterIterator(list.iterator(), new FilterPredicate());
for (;filterIterator.hasNext();) {
String s = (String) filterIterator.next();
assertEquals("Hello", s); // only "Hello" is returned
assertEquals(3, list.size()); // non destructive filtering
}
}
// the Predicate object. pretty simple
public class FilterPredicate implements Predicate {
public boolean evaluate(Object o) {
return ((String) o).equals("Hello");
}
}
To update a collection with only those objects that match the predicate (destructive filtering) we can use CollectionUtils.filter()
Building on the same test as before
public void testDestructiveFilter() {
ArrayList list = setupList();
assertEquals(3, list.size());
CollectionUtils.filter(list, new FilterPredicate());
assertEquals(1, list.size()); // other objects in list are stripped off
}
Similarly if we want to do a non destructive filtering.
public void testNonDestructiveFilterWhichMatches() {
ArrayList list = setupList();
// the select() keeps only those objects that evaluate to a 'true'
Collection newCollection = CollectionUtils.select(list, new FilterPredicate());
assertEquals(3, list.size());
assertEquals(1, newCollection.size());
}
public void testNonDestructiveFilterWhichDoesNotMatches() {
ArrayList list = setupList();
// I guess U know what this means by now :)
Collection newCollection = CollectionUtils.selectRejected(list, new FilterPredicate());
assertEquals(3, list.size());
assertEquals(2, newCollection.size());
}
using a Transformer
- used to perform a tranformation on each object in a collection
public void testBasicTransformer() {
final ArrayList list = setupList();
CollectionUtils.transform(list, new StringTransformer());
assertEquals("HELLO", list.get(0)); // "HELLO" converted to upper case
}
// my transformer class which converts to Upper Case
private static class StringTransformer implements Transformer {
public Object transform(Object o) {
return StringUtils.upperCase((String) o);
}
}
We can also chain transformers to do some pretty neat stuff.
We can also use Predicates to count number of objects in a Collection if we need to count depending upon a condition
// the Predicate used here returns 'true' only for "Hello" objects in the collection
public void testCountingNumberOfHellosInCollection() {
ArrayList list = setupList();
assertEquals(1, CollectionUtils.countMatches(list, new FilterPredicate()));
}
There are tons of other juicy bits hidden away. Explore maadi.