dazzle
dazzle

Reputation: 1346

Grouping objects in a map

This may be trivial, but I need to ensure I do it the correct way.

I have a person object which has property country_id. I need to group persons based upon country_id and then finally pack then into 1 Map object. The Map should have the key as the country_id and its value as List of person objects that belong to that country_id.

So the flow should be:

My final o/p should be PersonMap(country_id-<PersonList>,country_id-<PersonList> )

Is this approach correct or is there a better approach?

Upvotes: 0

Views: 5218

Answers (4)

nd.
nd.

Reputation: 8932

Guava has a nice index method, that returns a Multimap indexed by the expression.

ListMultimap<Integer, Person> multimap = Multimaps.index(personList, new Function<Person, Integer>(){
  public Integer apply(Person source){
    return source.getCountryId();
  }
});

The Multimap itself can be viewed as a Map, if you need that:

Map<Integer, Collection<Person>> map = multimap.asMap();

An even nicer, fluent API is available through LambdaJ's grouping function:

Group<Person> group = group(personList, by(on(Person.class).getCountryId()));

However, LambdaJ's Group object does not have any methods that convert it into a map, so you must do this from hand. But maybe you can change the interface so that you can return a Group.

Upvotes: 3

Greg
Greg

Reputation: 1719

Or you could use Google Guava project

Implementing GroupBy using Google guava Multimap and Function

This is one way of creating a group by like functionality for collections using google guava Multimap and Function.

Code is straight forward we simply use the index method of the Multimap to group our data by, in here we use our 2 column to group it by the department.

Sample output

key = Dev
  1 : Greg
  3 : Roman
key = Support
  2 : Leo
  4 : Jobby
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;

public class GroupByMultimap {
    public static void main(String[] args) {
        Object[] o1 = new Object[] { 1, "Greg", "Dev" };
        Object[] o2 = new Object[] { 2, "Leo", "Support" };
        Object[] o3 = new Object[] { 3, "Roman", "Dev" };
        Object[] o4 = new Object[] { 4, "Jobby", "Support" };

        List<Object[]> rows = Lists.newArrayList(o1, o2, o3, o4);
        Multimap<String, Object[]> grouped = Multimaps.index(rows,
                new Function<Object[], String>() {
                    @Override
                    public String apply(Object[] item) {
                        return (String) item[2];
                    }
                });

        Iterator<String> keyIterator = grouped.asMap().keySet().iterator();
        while (keyIterator.hasNext()) {
            String key = keyIterator.next();
            System.out.println("key = " + key);
            Collection<Object[]> dataRows = grouped.get(key);
            for (Object[] o : dataRows) {
                System.out.println(String.format("  %d : %s", o[0], o[1]));
            }
        }
    }
}

Upvotes: 2

NimChimpsky
NimChimpsky

Reputation: 47290

you could implement comparable on person object that uses country id as value to compare, your person objects could then be ordered by country.

Upvotes: 0

David Webb
David Webb

Reputation: 193706

You can put people in the Map as you loop through them. Simply look for the list you need in the map and if you don't find it create it and put it in the map.

Assuming country_id is an int and not using PersonMap as I don't know how that works:

Map<Integer,List<Person>> map = new HashHap<Integer,List<Person>>();

for (Person person : collectionOfPeople) {
    int cid = person.getCountryId();

    List<People> list = map.get(cid);

    if (list == null) {
        list = new ArrayList<People>();
        map.put(cid,list);
    }

    list.add(person);
}

Upvotes: 3

Related Questions