有没有一种方便的方法来创建一个谓词来测试一个字段是否等于一个给定的值? [英] Is there a convenience method to create a Predicate that tests if a field equals a given value?
问题描述
我经常发现自己需要过滤 Stream
或使用谓词来检查给定字段是否具有给定值。
说例如我有这个POJO:
public class A {
private Integer领域;
public A(最终整数字段){
this.field = field;
}
public Integer getField(){
return field;
$ / code $ / pre
我想过滤基于字段的值的流
:
final Integer someValue = 42;
Stream.of(new A(42),new A(1729),new A(42),new A(87539319),new A(null))
.filter(a - > Objects .equals(a.getField(),someValue))
...
是一种为过滤器
方法生成谓词的简便方法?我注意到有 Predicate.isEqual
但它不符合需要。
我可以很容易地写一个像这:
public static< T,R>谓词< T> isEqual(函数<?super T,?extends R> f,R value){
return v - > Objects.equals(value,f.apply(v));
}
并将其用作:
$ b $ (新A(42),新A(1729),新A(42),新A(87539319),新A(空))
.filter(isEqual(A :: getField,someValue))
...
但如果可能的话,我宁愿重复使用JDK中现有的方法。
没有这样的内建工厂方法,你可以通过查看 JFC中的 Predicate
的所有用法并查找返回谓词中的方法。除了 谓词
本身,只有 Pattern.asPredicate()
,它返回一个 Predicate
。
在你要实现这样的工厂方法之前,你应该问自己是否真的值得。是什么让你在 .filter(a - > Objects.equals(a.getField(),someValue))
中的lambda表达式看起来很复杂,是使用 Objects.equals
当你至少可以预测一个参数是否为 null
时,这是不必要的。从这里开始, someValue
永远不会 null
,您可以简化表达式:
final Integer someValue = 42;
Stream.of(new A(42),new A(1729),new A(42),new A(87539319),new A(null))
.filter(a - > someValue .equals(a.getField()))
...
如果你还想实现工厂方法,并赢得创造性地使用已有的东西的价格,您可以使用:
public static< T,R> ;谓词< T> isEqual(Function <?super T>?extends R> f,R value){
return f.andThen(Predicate.isEqual(value):: test):: apply;
}
然而,对于产品代码,我宁愿推荐一个这样的实现:
public static< T,R>谓词< T> isEqual(函数<?super T,?扩展R> f,R值){
返回值== null? t - > f.apply(t)== null:t - > value.equals(f.apply(T));
}
这会影响常数是否为 null
来简化每个测试中将要执行的操作。所以它仍然不需要 Objects.equals
。请注意, Predicate.isEqual
的确如此。
I often find myself in the need to filter a Stream
or to use a predicate that checks if a given field has a given value.
Say for example I have this POJO:
public class A {
private Integer field;
public A(final Integer field) {
this.field = field;
}
public Integer getField() {
return field;
}
}
And I want to filter a Stream
of objects based on the value of the field
:
final Integer someValue = 42;
Stream.of(new A(42), new A(1729), new A(42), new A(87539319), new A(null))
.filter(a -> Objects.equals(a.getField(), someValue))
...
Would there be a convenience method to generate the predicate for the filter
method? I noticed there is Predicate.isEqual
but it does not fit the need.
I could quite easily write one like this:
public static <T,R> Predicate<T> isEqual(Function<? super T, ? extends R> f, R value) {
return v -> Objects.equals(value, f.apply(v));
}
and use it as:
Stream.of(new A(42), new A(1729), new A(42), new A(87539319), new A(null))
.filter(isEqual(A::getField, someValue))
...
but I'd prefer to reuse an existing method from the JDK if possible.
There is no such builtin factory method, which you can easily check by looking at all usages of Predicate
within the JFC and look for "Methods in … that return Predicate". Besides the methods within Predicate
itself, there is only Pattern.asPredicate()
which returns a Predicate
.
Before you’re going to implement such a factory method, you should ask yourself whether it’s really worth it. What makes your lambda expression in .filter(a -> Objects.equals(a.getField(), someValue))
look complicated, is the use of Objects.equals
which is not necessary when you can predict for at least one argument whether it is null
. Since here, someValue
is never null
, you can simplify the expression:
final Integer someValue = 42;
Stream.of(new A(42), new A(1729), new A(42), new A(87539319), new A(null))
.filter(a -> someValue.equals(a.getField()))
…
If you still want to implement the factory method and win a price for creatively using what is already there, you can use:
public static <T,R> Predicate<T> isEqual(Function<? super T, ? extends R> f, R value) {
return f.andThen(Predicate.isEqual(value)::test)::apply;
}
However, for production code, I’d rather recommend an implementation like this:
public static <T,R> Predicate<T> isEqual(Function<? super T, ? extends R> f, R value) {
return value==null? t -> f.apply(t)==null: t -> value.equals(f.apply(t));
}
This factors out the test whether the constant is null
to simplify the operation that will be performed in each test. So it still doesn’t need Objects.equals
. Note that Predicate.isEqual
does similar.
这篇关于有没有一种方便的方法来创建一个谓词来测试一个字段是否等于一个给定的值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!