简体   繁体   中英

Break from the inner nested stream when no elements are passed through filter

Here is the example of code that I struggle with:

List<CategoryHolder> categories = ...
List<String> categoryNames = categoryIds.stream()
                    .map(id -> categories.stream()
                            .filter(category -> category.getId().equals(id))
                            .findFirst().get().getName())
                            .collect(Collectors.toList());

So I have a list of CategoryHolder objects consisting of category.id and category.name . I also have a list of category ids. I want to iterate through ids and for each id I want to iterate through the CategoryHolder list and when id from categoryIds list is matched with a CategoryHolder.id I want to return the category.name . So basically I want to map every value from categoryIds to its category.name .

So the problem is when no values are matched, filter doesn't pass any elements through and there is nothing to collect, so I would like to break from the current inner stream, and continue to the next id from categoryIds list. Is there a way to achieve this in stream API?

You can do like:

categories.stream()
            .filter(categoryHolder -> categoryIds.stream()
                          .anyMatch(id->categoryHolder.getId().equals(id)))
            .map(CategoryHolder::getName)
            .collect(Collectors.toList());

or for better performance you can do:

Map<String,CategoryHolder> map = categories.stream()
            .collect(Collectors.toMap(CategoryHolder::getId, Function.identity()));

List<String> names = categoryIds.stream()
            .map(id -> map.get(id).getName())
            .collect(Collectors.toList());

The problem is with your call to filter where you are doing .findFirst().get().getName()

This would fail in case empty Optional is returned by findFirst() .

You can instead rewrite it as follows:

List<String> categoryNames = 
          categoryIds
           .stream()
           .map(id -> categories
                       .stream()
                       .filter(catgory -> catgory.getId().equals(id))
                       .findFirst())
           .collect(
               ArrayList::new, 
               (list, optional) -> {
                    optional.ifPresent(categoryHolder -> list.add(categoryHolder.name));
                }, 
              (list, list2) -> {}
            );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM