可能将谓词与 `and` 链接以使用不同的类型参数吗?

huangapple go评论81阅读模式
英文:

Is it possible to chain predicates with `and` using different type parameter?

问题

我正在学习Java 8的lambda表达式。我可以使用Predicate接口中的"and"方法来合并两个具有不同类型参数的谓词吗?

以下是我的代码:

    Predicate<Integer> pc = (iv) -> iv > 20;
    Predicate<String> pL = (is) -> is.length() > 5;
    System.out.println("pc的谓词结果是:" + pc.test(25));
    System.out.println("===========");
    System.out.println("同时满足两个条件的谓词结果是:" + pc.and(pL).test("abcd"));
英文:

I am learning Java 8 lambdas. Can I join two predicates, with different type parameter, using and method in Predicate interface?

This is my code:

Predicate&lt;Integer&gt; pc = (iv) -&gt; iv &gt; 20;
Predicate&lt;String&gt; pL = (is) -&gt; is.length() &gt; 5;
System.out.println(&quot;The predicate result for pc is: &quot; + pc.test(25));
System.out.println(&quot;===========&quot;);
System.out.println(&quot;The predicate result with both condition true: &quot; + pc.and(pL.test(&quot;abcd&quot;)));

答案1

得分: 2

不可以,您不能链接不同类型的谓词,除非链接的 谓词 也接受原始谓词的类型。

从签名上看,您可以很容易地看到:
and(Predicate<? super T> other)
or(Predicate<? super T> other)

您可以链接谓词:

Predicate<Person> isMale = p -> p.isMale();
Predicate<Person> isAdult = p -> p.age() >= AGE_OF_MATURITY;
Predicate<Person> isAdultMale = isAdult.and(isMale);

您只能链接那些至少接受与原始谓词相同类型的谓词(这就是 ? super T 的意思):

Predicate<Object> hasWeirdHashCode = o -> o.hashCode() == 0;
Predicate<Person> nonsense = isMale.and(hasWeirdHashCode);

如果要测试不同的类型(AB),您需要分别提供它们:

Predicate<A> propertyOfA = [...];
Predicate<B> propertyOfB = [...];

BiPredicate<A, B> propertyOfAnB = (a, b) -> 
    propertyOfA.test(a) && propertyOfB.test(b);

如果您需要超过两种不同类型,您需要自己编写自定义的 TriPredicateQuadPredicate 等功能接口,实现起来应该很简单。

英文:

No, you can not chain predicates of different types, unless the chained predicate also accepts the type of the original predicate.

Looking at the signature, you can easily see that:
and(Predicate&lt;? super T&gt; other)
or(Predicate&lt;? super T&gt; other)

You can chain predicates:

Predicate&lt;Person&gt; isMale = p -&gt; p.isMale();
Predicate&lt;Person&gt; isAdult = p -&gt; p.age() &gt;= AGE_OF_MATURITY;
Predicate&lt;Person&gt; isAdultMale = isAdult.and(isMale);

You can only chain predicates that accept at least (thats what the ? super T says) the same type as the original predicate:

Predicate&lt;Object&gt; hasWeirdHashCode = o -&gt; o.hashCode() == 0;
Predicate&lt;Person&gt; nonsense = isMale.and(hasWeirdHashCode);

If you want to test different types (A, B), you need to provide them separately:

Predicate&lt;A&gt; propertyOfA = [...];
Predicate&lt;B&gt; propertyOfB = [...];

BiPredicate&lt;A,B&gt; propertyOfAnB = (a, b) -&gt; 
    propertyOfA.test(a) &amp;&amp; propertyOfB.test(b);

If you need more than two different types, you need to roll your own, custom TriPredicate, QuadPredicate and so on functional interfaces, which should be straight-forward to implement.

huangapple
  • 本文由 发表于 2020年10月1日 11:30:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/64148667.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定