Saturday, 15 September 2012

Manipulating collections with lambdaj

Java is not that nice regarding manipulations on collections even though tasks like iterating happen to us on a daily basis.

To ease the pain a little bit we can use the lambdaj library that allows manipulating collections without using loops.

Here is a simple unit test that shows some of lambdaj API and features
(Person class is a pojo with age and name fields, and implemented hashCode and equals methods):


private List<Person> people;
private Person robin;
private Person shinji;
private Person tom;
@Before
public void setUp() {
robin = new Person("Robin van Persie", 29);
shinji = new Person("Shinji Kagawa", 23);
tom = new Person("Tom Cleverley", 23);
people = asList(robin, shinji, tom);
}
@Test
public void selectsByAge() {
List<Person> resultIteratively = new ArrayList<>();
for (Person person : people) {
if (person.getAge() == 23) {
resultIteratively.add(person);
}
}
List<Person> resultWithLambda = select(people, having(on(Person.class).getAge(), equalTo(23)));
assertThat(resultIteratively, is(asList(shinji, tom)));
assertThat(resultWithLambda, is(asList(shinji, tom)));
}
@Test
public void sumsAge() {
int resultIteratively = 0;
for (Person person : people) {
resultIteratively += person.getAge();
}
int resultWithLambda = sum(people, on(Person.class).getAge());
assertThat(resultIteratively, is(75));
assertThat(resultWithLambda, is(75));
}
As you can see the code using lambdaj is much shorter and more readable.

The features of the library go far beyond that, there are many aggregation and filtering functions, as well as grouping, sorting and possibility to invoke a method for each collection's item.

The main drawback is that it's slower than standard iterative approach, so if speed is your concern, you need to watch out. However you can always use it in the unit tests.