Nooblhu Nooblhu - 10 days ago 11
Java Question

How to search inside a List<String> inside an abstract data type as attribute of other Abstract Data Type using the Java Stream API

I have a Library class that uses Set copies as a field.
This BookCopy has as attributes Book book and Condition c.
The Book class has String title, int year and List authors.
I'm implementing a method (using Streams) to search for title or authors using a string:

public List<Book> find(String query) {

Set<BookCopy> allCopies = this.copies;
//Set<BookCopy> becomes Set<Book> with only matching title books
Set<Book> booksByTitle = allCopies
.stream()
.map(BookCopy::getBook)
.filter(b -> b.getTitle().contains(query))
.collect(Collectors.toSet());
//Set<BookCopy> becomes Set<Book> with only matching authors books
Set<Book> booksByAuthor = allCopies
.stream()
.map(BookCopy::getBook)
.filter(b -> {
for (String s:b.getAuthors()){
s.contains(query);
}})
.collect(Collectors.toSet());

booksByTitle.addAll(booksByAuthor);

return new ArrayList<>(booksByTitle);
}


The BooksByTitle seems to be fine, however for BooksByAuthor the IDE throws an error saying:

( no type b) -> {} isn't applicable

How can I filter that Set so only books in which the authors list matches the query are passed?
Sorry about the crappy code, I'm just trying to make it work first and I'm just learning about Java stream API, and Java 8 features.

Answer

You should really look into anyMatch, as you are interested in only those books that have at least one author that you are interested in.

  .stream()
  .map(BookCopy::getBook)
  .filter(b -> b.authors.stream().anyMatch(a -> a.contains(query)))
  .collect(Collectors.toSet()));