Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Stream Api INNER JOIN Two Lists

Tags:

java

java-8

How to replace this code with using Java Stream Api?

for (Book book : Books.getAllBooks()) {
        for (SearchResult searchResult : searchResultList) {
          if (searchResult.getTableName().replace("attr_", "") .equals(book.getTableName())) {
            bookList.add(book);
          }
        }
      }
like image 934
Artur Avatar asked Apr 28 '16 11:04

Artur


4 Answers

List<Book> bookList = Books.getAllBooks().stream()
            .filter(e -> searchResultList.stream()
                         .anyMatch(f -> e.getTableName().equals(f.getTableName().replace("attr_", ""))))
            .collect(Collectors.toList());
like image 62
Somaiah Kumbera Avatar answered Sep 27 '22 21:09

Somaiah Kumbera


I came from C# and missed that feature in Java 8 API, so I wrote my own. With streamjoin you can write

Stream<Book> books = 
 join(Books.getAllBooks().stream())
 .withKey(Book::getTableName)
 .on(searchResultList.stream())
 .withKey(SearchResult::getTableName)
 .combine((book, searchResult) -> book)
 .asStream()
like image 35
Matthias Simon Avatar answered Sep 27 '22 21:09

Matthias Simon


Not exactly what you asked for, but here's another trick if you're using Guava:

List<Book> bookList = new ArrayList<>(Books.getAllBooks());
Lists.transform(bookList, Book::getTableName)
        .retainAll(Lists.transform(searchResultList, r -> r.getTableName().replace("attr_", ""));
like image 22
shmosel Avatar answered Sep 27 '22 21:09

shmosel


In my opinions, your example is a particular case of join operation, because your result set doesn't take any column of SearchResult. For most people going into this question like me, the general join operation with Java Stream is what they want. And here is my solution :

  • step 1, flatMap with judging whether the result should be null or not
  • step 2, filter the stream in step 1 by nonNull

It works fine, although it's not so elegant, which seems like u implement a join operation yourself--

The pseudocode may like :

//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);

like image 45
sch001 Avatar answered Sep 27 '22 20:09

sch001