How could I simplify this with Java stream library?

for (Issue issue : issues) {
     if (issue.getSubtasks().spliterator().estimateSize() > 0) {
         alreadyCreated = false;
         for (Subtask subtask : issue.getSubtasks()) {
            if (subtask.getSummary().contains("sometext")) {
                alreadyCreated = true;
                break;
            }
         }
         if (!alreadyCreated) {
            ids.add(issue.getKey());
         }
    } else {
         ids.add(issue.getKey());
    }
}

I'm not so expert with Java stream API, but I'm pretty sure there's some way to simplify the code above with using lambda expressions. Would be a great help to understand it even better!

Some notes: Issues and getSubtasks() are returning back Iterable<> types.

2 answers

  • answered 2021-02-23 20:51 Willis Blackburn

    You're adding the issue key to ids if there exists no subtask with a summary containing "sometext."

    issues.stream()
        .filter(i -> i.getSubtasks().stream()
            .noneMatch(s -> s.getSummary().contains("sometext")))
        .map(Issue::getKey)
        .forEach(ids::add);
    

    I think the subtasks size check is at least superfluous and possibly dangerous, if it's possible for it to estimate the size as zero when subtasks exist. But if getSubtasks() returns some non-collection that can't easily be streamed and this estimateSize() call is necessary then that just changes things a little bit:

    issues.stream()
        .filter(i -> {
            Spliterator<Subtask> split = i.getSubtasks().spliterator();
            return split.estimateSize() == 0 ||
                StreamSupport.stream(split, false)
                   .noneMatch(s -> s.getSummary().contains("sometext"));
        })
        .map(Issue::getKey)
        .forEach(ids::add);
    

  • answered 2021-02-23 22:10 iota

    You can use filter to remove unwanted elements and map to get the key, then collect to a List.

    StreamSupport.stream(issues.spliterator(), false).filter(x -> 
       StreamSupport.stream(x.getSubtasks().spliterator(), false)
         .noneMatch(y -> y.getSummary().contains("sometext"))
    ).map(Issue::getKey).collect(Collectors.toList());