这与我对“流减少不兼容类型”的回答有关。我不知道为什么我的建议有效,霍尔格正确地敦促我这一点。但即使是他似乎也没有一个明确的解释为什么它能起作用。所以,让我们把它作为自己的问题来问:
以下代码不能在javac
中编译(下面指向ideone的链接是sun-jdk-1.8.0_51
,请参阅http://ideone.com/faq):
public <T> Object with(Stream<Predicate<? super T>> predicates) {
return predicates.reduce(Predicate::or);
}
这样做是正确的:或者将这个流中的两个谓词结合在一起,就像写:
Predicate<? super T> a = null;
Predicate<? super T> b = null;
a.or(b); // Compiler error!
public <T> Object with(Stream<Predicate<? super T>> predicates) {
return predicates.map(a -> a).reduce(Predicate::or);
// ^----------^ Added
}
IdeOne演示
尽管事实上我想尝试这一点,但我不太清楚为什么这会起作用。我的解释是,.map(a->a)
的作用类似于“强制转换”,它给类型推断算法更大的灵活性来选择允许应用reduce
的类型。但我不确定到底是什么类型。
请注意,这并不等同于使用.map(function.identity())
,因为它被限制为返回输入类型。IdeOne演示
方法的返回类型可以变得更具体一些;我在上面省略了它,这样返回类型上的讨厌泛型就不会妨碍:
public <T> Optional<? extends Predicate<? super T>> with(
Stream<Predicate<? super T>> predicates) {
return predicates.map(a -> a).reduce(Predicate::or);
}
这是使用-xdverboseresolution=all
编译的输出。不完全确定这是否是我可以发布的调试类型推断的最相关的输出;如果有更好的建议,请告知:
Interesting.java:5: Note: resolving method <init> in type Object to candidate 0
class Interesting {
^
phase: BASIC
with actuals: no arguments
with type-args: no arguments
candidates:
#0 applicable method found: Object()
Interesting.java:7: Note: resolving method map in type Stream to candidate 0
return predicates.map(a -> a).reduce(Predicate::or);
^
phase: BASIC
with actuals: <none>
with type-args: no arguments
candidates:
#0 applicable method found: <R>map(Function<? super T#1,? extends R>)
(partially instantiated to: (Function<? super Predicate<? super T#2>,? extends Object>)Stream<Object>)
where R,T#1,T#2 are type-variables:
R extends Object declared in method <R>map(Function<? super T#1,? extends R>)
T#1 extends Object declared in interface Stream
T#2 extends Object declared in method <T#2>with(Stream<Predicate<? super T#2>>)
Interesting.java:7: Note: Deferred instantiation of method <R>map(Function<? super T#1,? extends R>)
return predicates.map(a -> a).reduce(Predicate::or);
^
instantiated signature: (Function<? super Predicate<? super T#2>,? extends Predicate<CAP#1>>)Stream<Predicate<CAP#1>>
target-type: <none>
where R,T#1,T#2 are type-variables:
R extends Object declared in method <R>map(Function<? super T#1,? extends R>)
T#1 extends Object declared in interface Stream
T#2 extends Object declared in method <T#2>with(Stream<Predicate<? super T#2>>)
where CAP#1 is a fresh type-variable:
CAP#1 extends Object super: T#2 from capture of ? super T#2
Interesting.java:7: Note: resolving method reduce in type Stream to candidate 1
return predicates.map(a -> a).reduce(Predicate::or);
^
phase: BASIC
with actuals: <none>
with type-args: no arguments
candidates:
#0 not applicable method found: <U>reduce(U,BiFunction<U,? super T,U>,BinaryOperator<U>)
(cannot infer type-variable(s) U
(actual and formal argument lists differ in length))
#1 applicable method found: reduce(BinaryOperator<T>)
#2 not applicable method found: reduce(T,BinaryOperator<T>)
(actual and formal argument lists differ in length)
where U,T are type-variables:
U extends Object declared in method <U>reduce(U,BiFunction<U,? super T,U>,BinaryOperator<U>)
T extends Object declared in interface Stream
Interesting.java:7: Note: resolving method metafactory in type LambdaMetafactory to candidate 0
return predicates.map(a -> a).reduce(Predicate::or);
^
phase: BASIC
with actuals: Lookup,String,MethodType,MethodType,MethodHandle,MethodType
with type-args: no arguments
candidates:
#0 applicable method found: metafactory(Lookup,String,MethodType,MethodType,MethodHandle,MethodType)
Interesting.java:7: Note: resolving method metafactory in type LambdaMetafactory to candidate 0
return predicates.map(a -> a).reduce(Predicate::or);
^
phase: BASIC
with actuals: Lookup,String,MethodType,MethodType,MethodHandle,MethodType
with type-args: no arguments
candidates:
#0 applicable method found: metafactory(Lookup,String,MethodType,MethodType,MethodHandle,MethodType)
除非我在FunctionalInterface推断是如何发生的方面遗漏了什么,否则很明显,您不能在流上调用reduce<?超级谓词>,因为它没有足够的类型来推断为BinaryOperator。
方法引用隐藏了故事的一个非常重要的部分,第二个参数。
return predicates.map(a->a).reduce((predicate, other) -> predicate.or(other));
如果移除对映射的调用,编译器就没有机会适当地键入流以满足第二个捕获要求。使用map,编译器可以决定满足捕获所需的类型,但是如果没有泛型的具体绑定,两个捕获只能用一个对象流来满足,这很可能是通过map()得到的结果。
public <T> Optional<? extends Predicate<? super T>> with(Stream<Predicate<Object>> predicates)
public <T> Optional<? extends Predicate<? super T>> with(Stream<Predicate<T>> predicates)
问题内容: 如果我尝试这样做: 我得到以下输出: 演示:http://codepad.org/ncVuJtJu 这是为什么? 我希望将其作为输出: 我的理解: 但是为什么不输出呢? 问题答案: 所有解释为什么得到2而不是1的答案实际上都是错误的。根据PHP文档,混合并以这种方式是不确定的行为,所以你可以得到1或2切换到不同版本的PHP可能会改变你得到的结果,这将是一样有效。 请参阅示例1,其中显示
我尝试了一些代码在Java中交换两个整数,而不使用第三个变量,即使用XOR。 以下是我尝试的两个交换函数: 该代码产生的输出如下: 我很想知道,为什么会有这样的说法: 和这个不一样?
这是CppCon谈话中的一个例子https://www.youtube.com/watch?v=F6Ipn7gCOsY 目标是首先从A打印Hello,然后允许线程B启动。很明显,应该避免繁忙等待,因为它占用大量CPU。 作者说, 循环可以由编译器进行优化(通过将 的值放入寄存器中),因为编译器看到 从不Hibernate,因此永远不会被更改。但是,即使线程从不Hibernate,另一个线程仍然可以
我总是假设当执行时,优化器自然会使用有效的按位操作,就像我写了
问题内容: 我尝试了一些代码,使用XOR在Java中交换两个整数而不使用第三个变量。 这是我尝试的两个交换函数: 这段代码产生的输出是这样的: 我很好奇,为什么这样说: 与这个不同吗? 问题答案: 问题是评估的顺序: 参见JLS第15.26.2节 首先,对左操作数求值以产生一个变量。 如果该评估突然完成,则赋值表达式由于相同的原因而突然完成;右边的操作数不会被评估,并且不会发生赋值。 否则,将保存
我有一个数组。我想对它们进行排序并删除重复项。这个答案建议使用和进行这种操作。运算的顺序不应该改变结果,所以我测量了计算的时间。 是什么使一个比另一个快?还有,有没有更快的办法呢?