Search code examples
javajava-streamgroupingcollectors

Grouping items in a list using Stream API


I'm trying to group items in a list using Stream.

public static void main(String[] args) {
    List<String> l = Arrays.asList("A", "C", "B", "A", "B");

    Map<String, List<String>> b = l.stream().collect(Collectors.groupingBy(Function.identity()));
    System.out.println(b.toString());
}

This returns {A=[A, A], B=[B, B], C=[C]}.

How can I get the index of each of those elements? Something like this, {A=[(A,0), (A,3)], B=[(B,2), (B,4)], C=[(C,1)]}.

This question is different from this question, where they want only the index, but I want both the index and the list item.


Solution

  • You can use groupingBy with List::get(int index) like this:

    Map<String, List<Integer>> result = IntStream.range(0, l.size())
            .boxed()
            .collect(Collectors.groupingBy(l::get));
    

    Output

    {A=[0, 3], B=[2, 4], C=[1]}
    

    As you can see, the response is a little different from what you expected. I believe displaying (B,2) is redundant.


    Edit

    As the OP insiste to show the same output, I would suggest to create a custom object that hold a letter and the index, like this:

    @AllArgsConstructor
    class MyOutput{
        private String letter;
        private Integer index;
    
        @Override
        public String toString() {
            return "(" + letter + "," + index + ')';
        }
    }
    

    And your stream should look like this:

    Map<String, List<MyOutput>> response = IntStream.range(0, l.size())
            .boxed()
            .collect(groupingBy(l::get, mapping(i -> new MyOutput(l.get(i), i), toList())));
    

    Outputs

    {A=[(A,0), (A,3)], B=[(B,2), (B,4)], C=[(C,1)]}