Search code examples
javajava-streamcollectorsgroupingby

can return java stream groupingby to this's array variable?


Q.1) hi, java stream's groupingby can make oneself's array varible?

this is entity

public class Test {
   private int id;
   private int itemId;
   private int[] itemIds;
   private boolean filter;
}

this is test List sample

{
   test(id=1, itemId=1)
   test(id=1, itemId=2)
   test(id=1, itemId=3)
   test(id=2, itemId=5)
   test(id=2, itemId=11)
}

And i want group by test.id, for example

{
   test(id=1, itemIds=[1,2,3])
   test(id=2, itemIds=[5,11])
}

what should i do?

tests.stream().collect(Collectors.groupingBy(Test::getId), ?, ?);

Q.2) how can i merge bellow two stream codes?

tests.stream().filter(Test::isFilter).anyMatch(t -> {throw new Exception;});
tests.stream().collect(Collectors.groupingBy(Test::getId, ?, ?); // Q1 result

about this..?

tests.stream().filter(Test::isFilter).anyMatch(t -> {throw new Exception;}).collect(Collectors.groupingBy(Test::getId, ?, ?);

Q3) above Q1, Q2's stream codes are better performance than java 'for' syntax?

Thank you in advance. :)


Solution

  • For grouping assuming a constructor like Test(int id, int itemId, int[] itemIds) and fluent getters such as id(), itemId() and itemIds() you could unflatten your data this way:

    List<Test> unflattenedTests = tests.stream()
       .collect(Collectors.groupingBy(Test::id))
       .entrySet().stream().map(e -> new Test(
           e.getKey().intValue(),
           0,
           e.getValue().stream().mapToInt(Test::itemId).toArray()
        ))
        .collect(Collectors.toList());
    

    As for merging your filter & throwing logic within a single statement I can't really think of any other way than peek such as:

    List<Test> unflattenedTests = tests.stream()
       .peek(t -> { if (t.isFilter()) throw new RuntimeException(); })
       .collect(...