其他方法;针对消费者和非消费者<和BiFunction><T,>然后().和BiFunction>
其他方法"Function<T,>操作符为compose(), andThen(), identity()。
其他方法"BinaryOperator<T,>andThen(), maxBy(), minBy().
其他方法"for Predicate is and(), or(), negate(), isEqual()。
其他方法"for BiPredicate<T,>Is and(), or(),否定()
既然函数接口是通过lambda表达式传递给实现方法的,那么谁来实现这些其他方法呢?
更新:我想指出的是;如果"其他方法"的语义;不是像下面评论中的例子那样琐碎或直接吗?考虑Predicate
功能接口。如果我传递一个lambda表达式到一个实现方法,但and(), or(), negate()
不是直截了当的。那么默认实现将不会覆盖它。我想我们将不得不处理我们自己的自定义功能接口,扩展原始接口并实现所有"其他方法"。
更新:对于像BiFunction
这样的函数接口,它有andThen()
其他方法,这是否意味着我们必须继承这个接口并创建一个带有默认方法andThen()
的新接口?
嗯,我觉得你遗漏了一些东西。
让我们考虑Predicate
接口。我删去了与问题无关的内容。
interface Predicate<T> {
boolean test(T t);
default Predicate<T> negate() {
return (t) -> !test(t);
}
}
这是一个功能接口:它只有一个抽象方法。该接口的作者还添加了一个方法,他们将其命名为negate
。它的实现返回一个新的Predicate
,当它的test
方法被调用时返回完全相反的结果。他们添加这个方法是因为他们认为它会很有用。
可以看到,negate
方法是默认的,并且有一个方法体。有主体的方法从来不是抽象的。
因为函数式接口是通过lambda表达式传递给实现方法的
和
如果我传递一个lambda表达式实现方法
不知道你在这里是什么意思,但我认为它的措辞很糟糕。lambda表达式只能在需要函数接口的地方使用。因此lambda表达式是函数式接口的唯一抽象方法的实现。"other"到目前为止,方法与这个故事无关。
比如说,我想创建一个Predicate
来测试字符串是否等于"Hello"典型的实现可能是这样的:
str -> str.equals("Hello")
这(大致)相当于:
class PredicateImpl implements Predicate<String> {
@Override
public boolean test(String t) {
return t.equals("Hello");
}
public Predicate<String> negate() {
return new Predicate<String> {
@Override
public boolean test(String t) {
return !PredicateImpl.this.test(t);
}
};
}
}
可以看到,negate()
返回一个新的谓词,该谓词捕获调用该方法的谓词,当调用其test
方法时,它被延迟到捕获的谓词,并返回结果布尔值的反转。
lambda表达式永远不会实现默认方法,因为它们不是抽象的。因此,negate
不会以任何方式被覆盖。
当然,这并不妨碍我们创建自己的函数接口来篡改否定的语义。
public interface MyPredicate<T> extends Predicate<T> {
@Override
public default MyPredicate<T> negate() {
return t -> true; // Say what?! That's not a negation!
}
}
现在让我们先看看"normal"谓词的作用:
String s = "Hello";
Predicate<String> stringIsHello = t -> t.equals("Hello");
Predicate<String> stringIsNotHello = stringIsHello.negate();
System.out.println(stringIsHello.test(s));
System.out.println(stringIsNotHello.test(s));
输出,如预期:
true
false
现在让我们使用自定义谓词:
String s = "Hello";
MyPredicate<String> p1 = t -> t.equals("Hello");
MyPredicate<String> p2 = p1.negate();
System.out.println(p1.test(s));
System.out.println(p2.test(s));
输出:
true
true
现在negate
在我们的MyPredicate
你期望它做什么?绝对不是。编译器是否阻止您实际执行此操作?不,它不能,也不会。
在再次阅读Lambdas的主题时,我有同样的问题,我回到这里,因为我不理解其他评论和答案。
我想也许答案是这样-andThen()
的参数是另一个函数接口;在本例中,另一个Consumer<T>
default Consumer<T> andThen(Consumer<? super T> after)
可以用不同的lambda链接方法andThen
条款
void foo(Consumer<T> consumer1Lambda, Consumer<T> consumer2Lambda) {
consumer1Lambda.test().andThen(consumer2Lambda);
}
实际上,是否需要实现该方法(或者即使可以)取决于Functional接口。例如,这里有一个BiConsumer
,它实现了accept
方法,然后链接了andThen
方法的后续实现。
BiConsumer<Integer, Integer> mathResults = (x, y) -> System.out
.printf("Here are the results for %s op %s:%n%n", x, y, x,y);
mathResults = mathResults.andThen((x,y)->System.out.printf("Addition: %s%n", x+y));
mathResults = mathResults.andThen((x,y)->System.out.printf("Subtraction: %s%n", x-y));
mathResults = mathResults.andThen((x,y)->System.out.printf("Multiplication: %s%n", x*y));
mathResults = mathResults.andThen((x,y)->System.out.printf("Division: %s%n", (double)x/y));
mathResults.accept(30,20);
打印
Here are the results for 30 op 20:
Addition: 50
Subtraction: 10
Multiplication: 600
Division: 1.5