Java Stream Api内部加入两个列表

时间:2016-04-28 11:18:53

标签: java java-8

如何使用Java Stream Api替换此代码?

for (Book book : Books.getAllBooks()) {
        for (SearchResult searchResult : searchResultList) {
          if (searchResult.getTableName().replace("attr_", "") .equals(book.getTableName())) {
            bookList.add(book);
          }
        }
      }

4 个答案:

答案 0 :(得分:6)

List<Book> bookList = Books.getAllBooks().stream()
            .filter(e -> searchResultList.stream()
                         .anyMatch(f -> e.getTableName().equals(f.getTableName().replace("attr_", ""))))
            .collect(Collectors.toList());

答案 1 :(得分:4)

我来自C#并且错过了Java 8 API中的这个功能,所以我写了自己的。 使用streamjoin,您可以编写

Stream<Book> books = 
 join(Books.getAllBooks().stream())
 .withKey(Book::getTableName)
 .on(searchResultList.stream())
 .withKey(SearchResult::getTableName)
 .combine((book, searchResult) -> book)
 .asStream()

答案 2 :(得分:1)

不是完全你所要求的,但如果你正在使用番石榴,这是另一招:

List<Book> bookList = new ArrayList<>(Books.getAllBooks());
Lists.transform(bookList, Book::getTableName)
        .retainAll(Lists.transform(searchResultList, r -> r.getTableName().replace("attr_", ""));

答案 3 :(得分:1)

在我看来,您的示例是联接操作的特例,因为您的结果集未包含SearchResult的任何列。对于大多数像我这样遇到此问题的人来说,他们想要的是 Java Stream的常规联接操作。这是我的解决方案:

  • 第1步,用flatMap判断结果是否为空
  • 第2步,通过nonNull过滤第1步中的流

它工作得很好,尽管它并不那么优雅,这似乎是您自己实现了一个连接操作-

伪代码可能类似于:

//init the two list
List l1 = ...;
List l2 = ...;

//join operation
res = l1.stream().flatMap(
    _item1 -> l2.stream().map(_item2 -> (_item1.join_key == _item2.join_key)?
         ([take the needed columns in item1 and item2]) : null
    )
).filter(Object::nonNull);