检查参数化谓词之间的相等性

Checking equality beetween parametrized predicate

我目前正在实施一种将谓词与文本字符串相匹配的方法

为了进行匹配,我正在填充

 的 Map,然后我可以通过谓词检索相应的字符串。

问题是当像下面的代码一样使用参数化谓词时,相同的谓词匹配不同的参数(散列函数中未使用 valueToTest)

public static Predicate<MyObject> predicateCondition(String valueToTest) {
    return myObject -> myObject.value.equals(valueToTest);
}

所以目前我需要为每个我想测试的参数创建一个谓词,即:

public static Predicate<MyObject> predicateConditionValue1() {
    return myObject -> myObject.value.equals("value1");
}

public static Predicate<MyObject> predicateConditionValue2() {
    return myObject -> myObject.value.equals("value2");
}

还有其他方法可以避免重复谓词吗?

您可以使用 BiFunction 作为替代:

BiFunction<MyObject, String, Boolean> isEquslTo = (myObject, expected) -> Objects.equals(myObject.value, expected);

但我更喜欢有两个 Predicate 的方法。

为了避免重复谓词,您应该使用 BiPredicate<T,U>,它接受一个多参数并生成一个 Boolean

BiPredicate<MyObject, String> biPredicate = (obj, string) -> myObject.value.equals(string)

方法中:

public static BiPredicate<MyObject, String> predicateConditionValue() {
     return (myObject, string) -> myObject.value.equals(string);
}

tl;博士:

首先你应该知道谓词不是class而是interface。 lambda 几乎是 anonymous classes(差异很小,这在您的问题范围内并不重要)。 所以你在问题中展示的所有三个函数,returns 对象是三个不同 classes 的实例(当然,它们都实现相同的接口,这就是为什么你可以使用所有的它们作为 Map 中的键)。 但是地图(实际上也是接口,因此您需要了解您在代码中使用的确切地图实现的工作原理)通常使用 equals()、hashCode(),有时可能使用 key-[= 的 compareTo() 36=]。并且因为您使用的是匿名 classes(严格来说:'almost anonymous classes'),它使用来自 class 对象的 equals() 和 hashCode()。其中 hashCode() 不依赖于对象方法和数据,而是由 JRE 创建,而 equals() 比较该哈希码。

简述:

不要使用匿名(声明为 lambda)谓词作为映射中的键。创建您自己的 class,它实现 Predicate 接口并拥有您自己的 hashCode()、equals() 和 test() 实现。如果您仍想使用 lambda,请使用这些匿名谓词作为您拥有的字段的键-class.

一般:

为避免此类问题,只需将 java 中的 Lambda 视为语法糖(lambda 不仅是语法糖,而且几乎是语法糖)。当您编写代码时:

Predicate<String> aPredicate= s->"asd".equals(s);

将其视为以下代码的特殊形式:

Predicate<String> aPredicate= new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return "asd".equals(s);
            }
        };