Monday, June 28, 2010

How to group by objects in java... in a simple way ?

Sometime it is very useful to group objects by some criteria.

We have a collection of Person we want to group by their Age.

public class Person {
    public String getName() {...}
    public int getAge() {...}
}

The first method we can use is the following :

Collection<Person> persons = ...;
Collection<Person>  personsAgeIs20 = new ArrayList<Person>();
for (Person person : persons) {
    if (person.getAge() == 20) {
         personsAgeIs20.add(person);
    }
}

Again, using google-collections, the magic class is Multimaps

Grouping Person by Age is as simple as this :

Collection<Person> persons = ...;
Map<Integer, Person> personsGroupByAge = Multimaps.index(persons, new Function<Person, Integer>() {
    public Integer apply(Person person) {
        return Integer.valueOf(person.getAge()); // Integer.valueOf because I don't like autoboxing :-p
    }
});
List<Person> personsAgeIs20 = personsGroupByAge.get(Integer.valueOf(20));

Ok, you tell me, same amout of line, why bother use Multimaps ? Because you don't code the grouping, you code the grouping logic only. Plus, with the first solution we have only grouped by 20, not by other ages. So, the Multimaps way is far more powerful and evolutive.

2 comments:

  1. How do you perform multi-level group by? for example Country --> State --> City --> Age and then count people at each level?


    ReplyDelete
    Replies
    1. With Guava (the new name for google-collection), you can provide function for each field you want to group by, ie, Person to country, Person to state...
      Then do a Multimaps.index from narrow field (age) to wider field (country) and calculate intermediate count result.

      But for complex query I would recommend using a database such as SQL one.

      Delete