Predicated Collections
In my project, Xml2Java, I had need for a code that checks reflection information, specifically methods and fields, and operates on relevant ones. For example, I wanted the code that analyses the elements and attributes of a complex element to work only on getter methods, that is, methods that begin with "get" or "is" and return a boolean.
At first, the code looked like this:
for (Method method : clazz.getMethods()) {
if (method.getName().startsWith("get") ||
(method.getName().startsWith("is") &&
method.getReturnType().equals(Boolean.TYPE))) {
// do stuff
}
}
It already looks ugly, but the problem really started when I discovered I had other places in my code which needed to work on collections of data in a conditional way. Before thinking too much and searching the web (and if I had, I would have found Apache's Common Collections) I wrote a simple utility class which offers static methods for decorating an Iterable class, making it yield only results that answer a specific predicate.
So now, after pre-creating predicates like these:
Predicate<Method> isBooleanGetter =
new Predicate<Method>(Method method) {
return method.getName().startsWith("is") &&
method.getReturnType().equals(Boolean.TYPE);
}
Predicate<Method> isRegularGetter =
new Predicate<Method>(Method method) {
return method.getName().startsWith("get");
}
Predicate<Method> isGetter =
new OrPredicate<Method>(
isRegularGetter, isBooleanGetter);
My code looks simple and clean:
for (Method method :
PredicateIterable.decorate(clazz.getMethods(), isGetter)) {
// do stuff
}
Simpler, cleaner, and the conditions are encapsulated into small pieces of conditional instances that can be reused and recombined later in other portions of the code. Also, in retrospect regarding Common Collections, they haven't switched to generics yet which makes my code type-safer, even if not as complete as theirs.
Comments (5)