检查参数化谓词之间的相等性
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);
}
};
我目前正在实施一种将谓词与文本字符串相匹配的方法
为了进行匹配,我正在填充
的 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);
}
};