Commons Collections By Example: Maps
I realized today just how much I used the Commons Collections library. Sure, there’s alot of anonymous inner classes, but after years of writing Swing I’ve gotten used to sort of crossing my eyes and looking past the syntactic cruft.
Here’s a silly example. Let’s map the names in the Greek alphabet to actual letters. Here’s our data
Map nameToLetter = new HashMap();
nameToLetter.put("ALPHA","a");
nameToLetter.put("BETA","b");
nameToLetter.put("GAMMA","g");
nameToLetter.put("DELTA","d");
String[] values = {"ALPHA","BETA","GAMMA","GAMMA","DELTA","EPSILON"};
List valueList = Arrays.asList(values);
Let’s convert that valueList to the letters:
Collection resultCollection = CollectionUtils.collect
(
valueList,
TransformerUtils.mapTransformer(nameToLetter)
);
System.out.println(resultCollection);
>[a, b, g, g, d, null]
Hmm…how do we go back the other way….
Map letterToName = MapUtils.invertMap(nameToLetter);
resultCollection = CollectionUtils.collect
(
resultCollection,
TransformerUtils.mapTransformer(letterToName)
);
System.out.println(resultCollection);
> [ALPHA, BETA, GAMMA, GAMMA, DELTA, null]
Notice that failed lookups return null. Maybe we don’t want a null…maybe we want an exception to be thrown. Maybe MapUtils has something for that…
Map guardedMap = MapUtils.lazyMap(nameToLetter, FactoryUtils.exceptionFactory());
CollectionUtils.collect
(
valueList,
TransformerUtils.mapTransformer(guardedMap)
);
> org.apache.commons.collections.FunctorException: ExceptionFactory invoked
Actually MapUtils.lazyMap is usually intended to automatically generate values for missing keys in the wrapped map, but we’re shortcircuiting and throwing an exception on a miss above.
For example, let’s try to fill in the blanks by guessing at the actual letter. How about the first letter of the name, lowercased (hint: don’t try something like this outside of an example)
Map guessingMap = MapUtils.lazyMap(nameToLetter,new Transformer()
{
public Object transform(Object o)
{
return ((String)o).substring(0,1).toLowerCase();
}
});
resultCollection = CollectionUtils.collect
(
valueList,
TransformerUtils.mapTransformer(guessingMap)
);
System.out.println(resultCollection);
> [a, b, g, g, d, e]
Note that the EPSILON:e mapping is now in the underlying nameToLetter map.
September 15th, 2006 at 8:29 pm
[…] A while back the Mission Data blog mentioned some of the cool tricks you could perform with the Jakarta Commons Collections, including the lazyMap. Here I’ll show you how I use lazyMaps to eliminate some plumbing code you’ve probably had to write before. […]