Java 使用Lambda和Streams For each并返回结果

Java 使用Lambda和Streams For each并返回结果,java,lambda,foreach,java-stream,Java,Lambda,Foreach,Java Stream,我最近一直在学习lambda和streams,并且很早就被抛入了深渊 我目前有一个书籍数组列表,用户键入一个单词,如果这个单词等于书籍作者或标题,则调用并返回books toString(书籍的所有属性都经过良好的格式化)。没有lambda很容易。但对于兰博达,我似乎不知道如何让这一切都实现 此外,使用lambda,我必须过滤掉数组中所有状态为“已损坏”或“已删除”的书籍 问题是,我必须返回流的结果,以最终显示在gui中,但似乎无法返回流的任何值 我有一个谓词,它将尝试匹配输入参数。 我不知道这

我最近一直在学习lambda和streams,并且很早就被抛入了深渊

我目前有一个书籍数组列表,用户键入一个单词,如果这个单词等于书籍作者或标题,则调用并返回books toString(书籍的所有属性都经过良好的格式化)。没有lambda很容易。但对于兰博达,我似乎不知道如何让这一切都实现

此外,使用lambda,我必须过滤掉数组中所有状态为“已损坏”或“已删除”的书籍

问题是,我必须返回流的结果,以最终显示在gui中,但似乎无法返回流的任何值

我有一个谓词,它将尝试匹配输入参数。 我不知道这是对还是错,我已经尝试得筋疲力尽了

我只是想知道我需要做些什么必要的改变才能让它正常工作

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

forEach
返回
void
,而您需要
字符串
。不过,我不会使用
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."));
}

我们可以用很多方法来做。我们应该在这里编写干净的代码,尽量避免在单个过滤器中使用多个加法条件,并将计算成本高的过滤器移到较低的阶。其次,您将在此处获得匹配书籍的列表,如:

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

}
公共列表getBookByTitleOrAuthor(字符串titleOrAuthor){
还书
.stream()
.filter(returnedBook.getBookStatus()!=Book.bookStatus.Damaged)
.filter(returnedBook.getBookStatus()!=Book.bookStatus.Deleted)
.过滤器(匹配标题作者(标题作者))
.collect(Collectors.toList());
}

在这里,如果您看到的话,代码更干净、易于阅读,并且只有在前两个被真正损坏和删除时才应用匹配过滤器。

老实说,这样的代码非常适合TDD,或者至少适合单元测试。因此,答案是:编写一个小单元测试。从一小份书籍清单开始,检查预期结果。然后,当测试失败时,只需进入调试器。除此之外,如果没有一个真正的代码,可能很难告诉你到底哪里有bug。非常感谢你,这段代码几乎可以完美地工作,但它似乎没有过滤掉被删除或损坏的书籍。我以为我已经用过滤器里的语句处理好了,但它似乎不起作用。我需要把if放在某个地方吗?@awyeanah2你能给我看看
getBookStatus()
Book.bookStatus
或者整个类吗?每本书都有一个bookStatus,它是enum@awyeanah2这很奇怪——第二种情况看起来还可以me@awyeanah2请包括整个班级以及如何填充
书籍
,我看不到全貌,所以我可能遗漏了一些重要的东西。现在我不需要重构/维护一个地方,而应该关注三个不同的地方。在我看来,一个很好的方法是有一个过滤器和一个对应的方法。性能方面没有区别,但这取决于具体情况。在我看来,可读且易于阅读的代码比使用多个逻辑运算符生成单个代码更重要。
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());

}