5

Is it possible to do the below mentioned steps using streams in a better way ?

Set<Long> memberIds = new HashSet<>();
marksDistribution.parallelStream().forEach(marksDistribution -> {
        memberIds.add(marksDistribution.getStudentId());
        memberIds.add(marksDistribution.getTeacherId());
      });

instanceDistribution.getStudentId() and instanceDistribution.getTeacherId() are both of type Long.

It might be possible that this kind of question is asked but I am not able to understand it. In simple yes or no. If yes/no, then how and bit explanation. And if possible kindly, discuss the efficiency.

0

2 Answers 2

9

Yes, you can use flatMap to map a single element of your Stream into a Stream of multiple elements, and then flatten them into a single Stream :

Set<Long> memberIds = 
    marksDistribution.stream()
                     .flatMap (marksDistribution -> Stream.of(marksDistribution.getStudentId(), marksDistribution.getTeacherId()))
                     .collect(Collectors.toSet());
Sign up to request clarification or add additional context in comments.

4 Comments

can you discuss the efficiency also compared to what I have done in question ?
@Eran 1+ from me, still if u have jdk-9 you could use a flatMapping collector: list.stream().collect(Collectors.flatMapping((MarksDistribution md) -> Stream.of(md.getStudentId(), md.getTeacherId()), Collectors.toSet()));
@Eugene Nice, I should probably try jdk-9 sometime soon.
@Eugene: like with all Stream operations, I would use the Collector counterpart only when necessary. You could express almost every Stream operation as a Collector-only operation, especially with Java 9, but it would be quiet hard to read…
5

You can use the 3-args version of collect:

Set<Long> memberIds = 
    marksDistribution.parallelStream()
                     .collect(HashSet::new, 
                              (s, m) -> {
                                   s.add(m.getStudentId());
                                   s.add(m.getTeacherId());
                               }, Set::addAll);

Your current version may produce wrong results, since you are adding elements in parallel in a non-thread safe collection. So it may be possible that you have multiple times the same value in the set.

5 Comments

can you discuss the efficiency also compared to what I have done in question ?
@balboa_21 The problem is that what you have done is flawed. Before thinking about efficiency, you should think about correctness. That said, using collect is the canonical way to get what you want using streams.
c: Thanks you for the quick response. Ok, if supposedly, I am not using parallelStream() ?.
@balboa_21 Still use collect. Otherwise you are left with a piece of code that won't work if someone decide to change in the future .stream() to .parallelStream().
@balboa_21: if you are not using a parallel operation, you can use forEach directly on the Collection, i.e. without a Stream operation at all.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.