5

How to convert following code using stream without using for each loop.

  1. getAllSubjects() returns all List and each Subject has List<Topic>. all List should be combined as List<Topic>.
  2. Needs to get Map<id,topicName> from List<Topic>

Object Model:

Subject
  id,....
  List<Topic>
Topic
  id,name

public Map<String, String> getSubjectIdAndName(final String subjectId) {

    List<Subject> list = getAllSubjects(); // api method returns all subjects
    //NEEDS TO IMPROVE CODE USING STREAMS
    list = list.stream().filter(e -> e.getId().equals(subjectId)).collect(Collectors.toList());
    List<Topic> topicList = new ArrayList<>();
    for (Subject s : list) {
        List<Topic> tlist = s.getTopics();
        topicList.addAll(tlist);
    }
    return topicList.stream().collect(Collectors.toMap(Topic::getId, Topic::getName));

}
Lakshman Miani
  • 344
  • 1
  • 5
  • 20
  • Please show your attempts. – Flown Feb 28 '18 at 10:17
  • 8
    Just remove these intermediate collections into `List`s, then, study [`flatMap`](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#flatMap-java.util.function.Function-) and you’re done. In other words, `return getAllSubjects() .stream() .filter(e -> e.getId().equals(subjectId)) .flatMap(s -> s.getTopics().stream()) .collect(Collectors.toMap(Topic::getId, Topic::getName));` – Holger Feb 28 '18 at 10:21
  • @Holger seems like the answer rather than a comment. ;) – Peter Lawrey Feb 28 '18 at 10:26
  • Thank you @Holger – Lakshman Miani Feb 28 '18 at 10:26

1 Answers1

9

Use flatMap here, to not stream again. Just notice that this toMap assumes that there will be no duplicate keys (or nulls)

list.stream()
    .filter(e -> subjectId.equals(e.getId()))
    .flatMap(subject -> subject.getTopics().stream())
    .collect(Collectors.toMap(Topic::getId, Topic::getName));
Eugene
  • 117,005
  • 15
  • 201
  • 306