Skip to content

Using Lambda and Streams in For each and returning result

i am have been learning lambda and streams lately and have kind of been thrown into the deep end really early.

I currently have an array list of books, a user types in a word and if the word equals the books author or title, the books toString(all attributes of the book nicely formatted) is called and returned. Very easy without lambda. But with lambda i just cant seem to figure out how to get it all to work out.

Additionally with the lambda i have to filter out all the books in the array that have a status of damaged or deleted.

The thing is i have to return the results from the stream to eventually display in a gui but cant seem to return any value of a stream.

I have a predicate which will try to do the matching of input parameters. I have no idea if this is right or not and i am pretty burnt out with trying.

I was just wondering the necessary changes i need to make to get this to work?

public String getBookByTitleOrAuthor(String titleOrAuthor) {
    books.stream()
         .filter(BookPredicate.matchTitleOrAuthor(titleOrAuthor))
         .filter(returnedBook -> returnedBook.getBookStatus() != 
            Book.bookStatus.Damaged && returnedBook.getBookStatus() != 
            Book.bookStatus.Deleted)
         .forEach(returnedBook -> returnedBook.toString());

}


// My predicate
public static Predicate<Book> matchTitleOrAuthor(String titleOrAuthor) {
    return b -> titleOrAuthor.equals(b.getTitle()) || 
    titleOrAuthor.equals(b.getAuthor());
}

Thanks in advance guys! sorry if this is a silly question.

My book status enum and getBookStatus:

 public bookStatus getBookStatus() {
         return this.bookStatus;
    }

      public enum bookStatus {
       Available,
       Reserved,
       Borrowed,
       Damaged,
       Deleted

     }

Answer

forEach returns void whereas you need a String. I wouldn’t go with String, though. The method says “I return a book by title or author”, so the user would expect a Book instance.

public Book getBookByTitleOrAuthor(String titleOrAuthor) {
    return books.stream()
                .filter(BookPredicate.matchTitleOrAuthor(titleOrAuthor))
                .filter(b -> {
                               final Book.bookStatus status = b.getBookStatus();
                               return status != null && 
                                      status != Book.bookStatus.Damaged && 
                                      status != Book.bookStatus.Deleted; 
                })  // can be moved into a BookPredicate method as well
                .findAny()
                .orElseThrow(() -> new IllegalArgumentException("There is no book for the given author or title."));
}