【问题标题】:Predicate all non null fields谓词所有非空字段
【发布时间】:2019-09-27 17:31:58
【问题描述】:

我有一个简单的 Book 类,其中包含类似

的字段
private String ISBN;
private String title;
private String author;

我想创建搜索查询,它将BookDto 作为条件,并将所有不可为空的字段与我的List<Book> 的元素进行比较。所以我写了几个简单的Predicates

private Predicate<Book> matchingAuthor(Book another) {
    return book -> book.getAuthor() != null && book.getAuthor().equals(another.getAuthor());
}

private Predicate<Book> matchingTitle(Book another) {
    return book -> book.getTitle() != null && book.getTitle().equals(another.getTitle());
}

private Predicate<Book> matchingISBN(Book another) {
    return book -> book.getISBN() != null && book.getISBN().equals(another.getISBN());
}

我希望有 1 种搜索方法来处理所有逻辑

private List<BookDto> findMatchingBooks(BookDto criteria) {
        return books.stream().map(BookConverter::toEntity).filter(this::matchingBook).map(BookConverter::toDto).collect(Collectors.toList());
}

但是这个逻辑很丑……而且它不会像我想要的那样工作。

private Predicate<Book> matchingBook(Book criteria) {
    if(criteria.getISBN() != null) {
        return matchingISBN(criteria);
    } 
    else if(criteria.getISBN() == null && criteria.getTitle() == null && criteria.getAuthor() != null) {
        return matchingAuthor(criteria);
    }
     else if(criteria.getISBN() == null && criteria.getTitle() != null && criteria.getAuthor() != null) {
        return matchingAuthor(criteria) && matchingTitle(criteria);
    }
}

前两个if/else 可以说是好的(丑陋但有效),第三个是导致

二元运算符'&&'的错误操作数类型 第一种:谓词 第二种:谓词

问题是,我怎样才能做到这一点?

【问题讨论】:

  • 如何在Book 类本身中添加一些布尔方法,例如boolean hasSameAuthor(Book other)?
  • 旁白:不清楚return books.stream().map(BookConverter::toEntity).filter(this::matchingBook).map(BookConverter::toDto).collect(Collectors.toList()); 正在执行什么。 filter(this::matchingBook) 如何处理当前签名?另请注意 matchingBook 方法中缺少返回。可以默认为真为return book -&gt; true;
  • 只是一种预感,您可能正在寻找一个简单的链式或条件来逐个匹配属性,否则返回 false。像:matchingISBN(criteria).or(matchingAuthor(criteria)).or(matchingTitle(criteria));
  • 你的条件是多余的。当您使用if(criteria.getISBN() != null) { …} 时,您不需要else if(criteria.getISBN() == null …,因为此时它必须是null。这同样适用于其他条件。此方法甚至无法编译,因为编译器无法识别冗余,并会说最后必须有另一个return。只需使用return criteria.getISBN() != null? matchingISBN(criteria): criteria.getTitle() == null? matchingAuthor(criteria): matchingAuthor(criteria).and(matchingTitle(criteria));

标签: java java-stream predicate


【解决方案1】:

您需要使用and 组合您的谓词:

return matchingAuthor(criteria).and(matchingTitle(criteria));

返回一个组合谓词,表示此谓词与另一个谓词的短路逻辑与。

【讨论】:

  • 关于它应该是Or的逻辑。 1) 匹配 isbn 或 2) 匹配作者...
  • @swinkler:你从哪里得到的?
  • 也许我误读了 MatchingBook 方法,它指出:如果存在 isbn,则返回 isbn 谓词。或者:如果作者(并且唯一的作者)存在,则返回作者谓词...为什么和?
  • 因为return matchingAuthor(criteria) &amp;&amp; matchingTitle(criteria)。如果两者都存在,则两者必须匹配。
  • 当然。这是最后一个条件。我之前写过这两个。
【解决方案2】:

您必须使用Predicate::and 组合Predicates

return matchingAuthor(criteria).and(matchingTitle(criteria));

default Predicate&lt;T&gt; and(Predicate&lt;? super T&gt; other):

返回一个组合谓词,表示此谓词与另一个谓词的短路逻辑与。在评估组合谓词时,如果该谓词为假,则不评估另一个谓词。 在评估任一谓词期间抛出的任何异常都将转发给调用者;如果对该谓词的评估引发异常,则不会评估另一个谓词。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-21
    • 2016-11-08
    • 1970-01-01
    • 2017-10-03
    • 1970-01-01
    • 1970-01-01
    • 2014-10-31
    • 1970-01-01
    相关资源
    最近更新 更多