Java Stream API INNER JOIN 两个列表



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

for (Book book : Books.getAllBooks()) {
        for (SearchResult searchResult : searchResultList) {
          if (searchResult.getTableName().replace("attr_", "") .equals(book.getTableName())) {
            bookList.add(book);
          }
        }
      }
List<Book> bookList = Books.getAllBooks().stream()
            .filter(e -> searchResultList.stream()
                         .anyMatch(f -> e.getTableName().equals(f.getTableName().replace("attr_", ""))))
            .collect(Collectors.toList());

我来自 C#,错过了 Java 8 API 中的该功能,所以我编写了自己的功能。使用流加入,您可以编写

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

完全是你要求的,但如果你使用番石榴,这里有另一个技巧:

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

,您的示例是连接操作的特殊情况,因为您的结果集不需要任何SearchResult列。对于像我一样进入这个问题的大多数人来说,使用 Java Stream 的一般连接操作是他们想要的。这是我的解决方案:

  • 步骤1,平面映射判断结果是否应为空
  • 步骤
  • 2,按非 Null 筛选步骤 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);

最新更新