Warm tip: This article is reproduced from stackoverflow.com, please click
grouping java java-8 java-stream

Java 8 group by String

发布于 2020-04-11 22:04:22

Here is my code:

public class StudentData {

    public static List<Student> getData() {

        return Arrays.asList(
            new Student(1, "a1", 1, Arrays.asList("cricket", "football", "basketball")),
            new Student(2, "a2", 1, Arrays.asList("chess", "football")),
            new Student(3, "a3", 2, Arrays.asList("running")),
            new Student(4, "a4", 2, Arrays.asList("throwball", "football")),
            new Student(5, "a5", 3, Arrays.asList("cricket", "basketball")),
            new Student(6, "a6", 4, Arrays.asList("cricket")), new Student(7, "a7", 5, Arrays.asList("basketball")),
            new Student(8, "a8", 6, Arrays.asList("football")),
            new Student(9, "a9", 8, Arrays.asList("tennis", "swimming")),
            new Student(10, "a10", 8, Arrays.asList("boxing", "running")),
            new Student(11, "a11", 9, Arrays.asList("cricket", "football")),
            new Student(12, "a12", 11, Arrays.asList("tennis", "shuttle")),
            new Student(13, "a13", 12, Arrays.asList("swimming"))
        );
    }

}

How to group the student based on hobbies. I tried this below code:

List<Student> data = StudentData.getData();
data.stream().collect(Collectors.groupingBy(s -> s.getHobbies().stream()));

It is not giving the right answer.

Questioner
Learn Hadoop
Viewed
51
Eugene 2018-05-18 20:39

You basically need a Stream that is made out of a Pair (I choose AbstractMap.SimpleEntry here) that has the left part as a Hobby and right as the Student (could be the other way around, does not matter).

Later just group those based on Hobby (that is a String in your case).

data.stream()
    .flatMap(student -> student.getHobbies().stream().map(hobby -> new SimpleEntry<>(hobby, student)))
    .collect(Collectors.groupingBy(
            Entry::getKey,
            Collectors.mapping(Entry::getValue, Collectors.toList())
));

Entry::getKey being a method reference that gets the key, you could write it as a lambda expression too, if it makes more sense for you:

Collectors.groupingBy(entry -> entry.getKey())