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):
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | |
} |
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.