amonxu
amonxu

Reputation: 349

How do I split a collection into subcollections?

I have a List of Users, who have a name and an age. I would like to split this list into sublists, where each list contains all the users with a particular age.

Here's some code for an example:

public class User{
    public String name;
    public int age;
}

User user1 = new User();
user1.setName("Tom");
user1.setAge("20");

User user2 = new User();
user2.setName("Jack");
user2.setAge("21");

User user3 = new User();
user3.setName("Peter");
user3.setAge("21");

List<User> userList = new ArrayList<User>();
userList.add(user1);
userList.add(user2);
userList.add(user3);

How can I can split userList so List1 (holding users age 20) contains Tom and List2(holding users age 21) contains Jack and Peter?

Upvotes: 0

Views: 455

Answers (4)

Steve K
Steve K

Reputation: 4921

If you want to use the Streams API to do this, you can use the GroupingBy collector:

Map<Integer, List<User>> groupedByAge = users.stream()
    .collect(Collectors.groupingBy((u)->u.age));

List<User> age20 = groupedByAge.get(20); // contains Tom
List<User> age21 = groupedByAge.get(21); // contains Jack, Peter

If you want all users over a certain age, and they're not conveniently all the same age, you can either collect from the map, or you can change your groupingBy function to this:

Map<Boolean, List<User>> groupedByAge = users.stream()
    .collect(Collectors.groupingBy((u)->u.age>20));

List<User> ageUnder21 = groupedByAge.get(false);
List<User> age21AndOver = groupedByAge.get(true);

Upvotes: 0

niekname
niekname

Reputation: 2616

If you are using java 8, you could use lambda's for this as explained in this post -> Java lambda sublist

If you're not using java 8, then I would also go with a Map implementation holding the age as key and the list as value.

Upvotes: 0

merlin2011
merlin2011

Reputation: 75555

It looks like you want to create a Map<Integer, List<User>> which will map ages to lists of users.

Map<Integer, List<User>> myMap = new HashMap<Integer, List<User>>();
for (User u: userList) {
   if (!myMap.containsKey(u.age)) myMap.put(u.age, new ArrayList<User>());
   myMap.get(u.age).add(u);
}

If you then want to iterate over them and print it out, you can iterate over the Map like this.

for (Integer i : myMap.keySet()) {
    System.out.print(i + ": ");
    StringBuilder sb = new StringBuilder();
    for (User u: myMap.get(i))
       sb.append("," + u.name);
    System.out.println(sb.toString().substring(1)); // Remove the first comma
}

Output:

21: Jack,Peter
20: Tom

Note that if you had wanted the Map to iterate in order by age, you can replace HashMap with TreeMap above, with the realization that your insertions and accesses will be O(log n) instead of O(1).

Upvotes: 3

gyanu
gyanu

Reputation: 995

Use Map with key age and value User List as follows

Map<Integer,List<User>> userMap = new HashMap<Integer,List<User>>();

Then, whenever you want to add a new age you put a new empty list and
public void addNewAge(Integer age) {
    userMap.put(age, new ArrayList<User>());
}

When you want to add a user, you obtain the user list based on the age represented by a Integer.
public void addUserToList(Integer age, User user) {
    if(userMap.containsKey(age))
        userMap.get(age).add(user);        
}

make little more look on Map So that it will comfort for you.

Upvotes: 1

Related Questions