当实现谓词而不是布尔值时

When implement Predicate instead of boolean

我正在阅读 ,当我看到评论时: 任何时候我发现自己需要一个多行 lambda,我将这些行移动到一个私有方法并传递该方法引用而不是 lambda。

我在问:实现这种行为的正确方法是什么?使用评论中发布的布尔方法,还是使用谓词?


示例: 假设我想检查 Table 是否可用,其中可用表示 isCleanisEmptyhasChair.

class Table{
    public boolean hasChair(){...}
    public boolean isClean(){...}
    public boolean isEmpty(){...}
}

我可以通过两种方式对我的列表 List<Table> tablesList = Arrays.asList(table1,table2,table3,table4); 进行过滤测试:第一种是布尔值:

public boolean isUsable(){
    return hasChair() && isClean() && isEmpty();
}

并与tablesList.stream().filter(Table::isUsable)

一起使用

第二种方式是谓词:

public Predicate<Table> isUsable(){
    return table -> table.isEmpty() && table.isClean() && table.hasChair();
}

可用于 tablesList.stream().filter(isUsable())


哪个是正确的实施方式?为什么选择一个而不是另一个?有什么大的不同吗?

我想你指的是第二个例子

public static Predicate<Table> isUsable(){
    return table -> table.isEmpty() && table.isClean() && table.hasChair();
}

这可能已经表明这种形式很可能会混淆 reader。没有 static 你可以写 table.isUsable()Table::isUsable 但它不会像你想的那样。

Which is the correct implementation?

我更喜欢 Table::isUsable,因为它也可以用作实例的 table.isUsable

Why choose one instead of other?

我觉得第一个例子更自然,不那么令人困惑。

第二种形式对于操作谓词更有用,例如Predicate.or(谓词)

Is there any big difference?

在这种情况下,使用 Stream 可能会更慢,但更重要的是,更容易混淆。

返回谓词的方法的一个优点是它可以添加到任何 class 例如由于某些原因,您无法更改 Table。

拥有 Predicate<Table> isUsable() 假设您始终需要在需要 Predicate<Table> 实例的地方使用该逻辑,这是一个限制。

另一方面,拥有 boolean isUsable() 可以让您灵活地使用 Table::isUsable 需要 Predicate<Table>,或者使用 Table::isUsable 作为其他功能的实现接口(匹配该方法的签名)或直接调用 t.isUsable() 特定的 Table 实例。因此我发现这个替代方案更有用。

static List<Predicate<Table>> predicateList = Arrays.asList(Table::hasChair, Table::isClean);

static boolean isUsable(Table table) {
    return predicateList.stream().allMatch(p -> p.test(table));
}

使用可用:

List<Table> tablesList = ...
Stream<Table> usableTables = tablesList.stream().filter(Table::isUsable);