Reputation: 1346
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:
country_id
and put in a list. e.g person A(id=10)
in list_Aperson B(id-20)
in list_BMy 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
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
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.
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
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
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