Using Lambdas Effectively in Java
One of the most powerful features python offers is lambdas which allow you to perform operations on a collection and create anonymous functions on the data set to filter, map (transform) or reduce. Here’s a snippet of code that outlines converting a complex meta data structure filtering on a repeating group and extracting out the position and sorting it and converting it to a displayable list.
metas = get_rows('META')
definition_row = filter(lambda r: get_str_val(r, 'display') == table_name, metas)[0]
var_groups = definition_row['data']['LAYOUT'].values()
var_groups = filter(lambda var_group: 'position' in var_group, var_groups)
var_groups = sorted(var_groups, key=lambda x: x['position'])
header_cap_ids = map(lambda var_group: var_group['display'], var_groups)
Now if we’re planning to do this in Java, it will be slightly more complicated and verbose. Without having Java 8 at our disposal (restricted by our app server version deployment), we’re limited to other frameworks (primarily LambaJ and Guava). LambaJ proved to be a little cumbersome and felt too integrated to the ORM model (similar to LINQ query) so Guava proved to be a better alternative. It is still a little verbose with with new anonymous classes being created per operation but it gets the gist what needs to be done.
DataRow row = CollectionUtils.getFirst(ThriftDBUtils.getAllRows("META"));
List<DataGroup> groups = ThriftDataUtils.getGroups(row, "CONTENT", "LAYOUT");
List<DataGroup> filter = CollectionUtils.filter(groups, new Predicate<DataGroup>()
{
@Override
public boolean apply(DataGroup group)
{
String stringValue = ThriftDataUtils.getStringValue(group, "position");
return !StringUtils.isEmpty(stringValue);
}
});
CollectionUtils.sort(filter, new Comparator<DataGroup>()
{
@Override
public int compare(DataGroup group1, DataGroup group2)
{
long long1 = Long.parseLong(ThriftDataUtils.getStringValue(group1, "position"));
long long2 = Long.parseLong(ThriftDataUtils.getStringValue(group2, "position"));
return ComparisonChain.start()
.compare(long1, long2)
.result();
}
});
List<String> transform = CollectionUtils.transform(filter, new Function<DataGroup, String>()
{
@Override
public String apply(DataGroup group)
{
String stringValue = ThriftDataUtils.getStringValue(group, "display");
return stringValue;
}
});
There is a word of caution submitted by the Guava team on excessive use of lambdas which can lead to confusing, unreadable and inefficient code when a simple iterative function will do. Concerning ourselves, I find it useful when performing series of operations that will change frequency and deals with converting or filtering on a complex data set.