Использование лямбды и потоков в каждом для каждого и возвращаемый результат - PullRequest
5 голосов
/ 16 мая 2019

В последнее время я изучаю лямбду и потоки, и меня очень рано бросили в глубокий конец.

В настоящее время у меня есть список книг в массиве, пользователь вводит слово, и если слово равно автору или названию книги, вызывается и возвращается toString книг (все атрибуты книги красиво отформатированы). Очень легко без лямбды. Но с лямбдой я просто не могу понять, как заставить все это работать.

Кроме того, с помощью лямбды я должен отфильтровать все книги в массиве, которые имеют статус поврежденных или удаленных.

Дело в том, что я должен возвращать результаты из потока, чтобы в итоге отобразить их в графическом интерфейсе, но, похоже, не могу вернуть любое значение потока.

У меня есть предикат, который попытается сопоставить входные параметры. Я понятия не имею, правильно это или нет, и я довольно сгорел от попыток.

Мне просто интересно, какие необходимые изменения мне нужно сделать, чтобы это заработало?

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());
}

Заранее спасибо, ребята! извините, если это глупый вопрос.

Перечисление статуса моей книги и getBookStatus:

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

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

     }

Ответы [ 2 ]

2 голосов
/ 16 мая 2019

forEach возвращает void, тогда как вам нужен String.Я бы не пошел с String, хотя.Метод говорит: «Я возвращаю книгу по названию или автору», поэтому пользователь может ожидать Book экземпляр.

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."));
}
1 голос
/ 16 мая 2019

Мы можем сделать это многими способами. Мы должны написать чистый код здесь и попытаться избежать нескольких условий добавления в одном фильтре и переместить фильтры, которые имеют высокие вычислительные затраты, в более низкий порядок. Во-вторых, вы получите список подходящих книг здесь:

public List<String> getBookByTitleOrAuthor(String titleOrAuthor) {
        return books
            .stream()
            .filter(returnedBook.getBookStatus() != Book.bookStatus.Damaged)
            .filter(returnedBook.getBookStatus() != Book.bookStatus.Deleted)
            .filter(matchTitleOrAuthor(titleOrAuthor))
            .map(Book::toString)
            .collect(Collectors.toList());

}

И если вы хотите только первый матч, используйте это:

public String getBookByTitleOrAuthor(String titleOrAuthor) {
        return books
            .stream()
            .filter(returnedBook.getBookStatus() != Book.bookStatus.Damaged)
            .filter(returnedBook.getBookStatus() != Book.bookStatus.Deleted)
            .filter(matchTitleOrAuthor(titleOrAuthor))
            .map(Book::toString)
            .findFirst()
            .orElse(null);
}

А если вам нужен список книг, тогда вам не нужна карта:

public List<Book> getBookByTitleOrAuthor(String titleOrAuthor) {
        return books
            .stream()
            .filter(returnedBook.getBookStatus() != Book.bookStatus.Damaged)
            .filter(returnedBook.getBookStatus() != Book.bookStatus.Deleted)
            .filter(matchTitleOrAuthor(titleOrAuthor))
            .collect(Collectors.toList());

}

Здесь, если вы видите, код более чистый, легкий для чтения и сопоставления фильтр применяется только тогда, когда первые два являются истинными поврежден и удален.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...