为什么以下代码仅在过滤谓词行被注释掉时才起作用。使用过滤器行,它会给我这个错误:
Incompatible types: java.lang.Object cannot be converted to java.lang.String
我做错了什么?
import static java.util.stream.Collectors.joining;
import java.util.Arrays;
import java.util.function.Predicate;
import java.util.regex.Pattern;
public class PredicateStreamInvalidType {
public static void main(String[] ignored) {
String input = "one two three four five six seven eight";
Predicate containsAnE = Pattern.compile("e").asPredicate();
String[] splits = input.split(" ");
String output = Arrays.stream(splits).
//filter(containsAnE).
collect(joining(" "));
System.out.println(output);
}
}
我期待这个输出:
one three five seven eight
答案 0 :(得分:4)
您正在使用Predicate<T>
的原始格式 - 使用原始类型通常是您最终遇到涉及Object
的编译时错误,您希望使用更具体的类型
您需要做的就是更改containsAnE
的编译时类型:
Predicate<String> containsAnE = Pattern.compile("e").asPredicate();
声明 Pattern.asPredicate
返回Predicate<String>
,所以你应该好好去:)
作为一种帮助您将来避免此类问题的方法,您应该看看是否可以使用任何您正在使用的环境(IDE,命令行编译等)来警告您使用原始类型时。它几乎总是一个坏主意。
答案 1 :(得分:1)
Arrays.stream(splits)
返回Stream<String>
Stream<String>.filter
方法有签名
Stream<String> filter(Predicate<? super String> predicate)
这适用于参数containsAnE
,它是一个原始的Predicate
,通过未经检查的转换。现在发生了一件有趣的事情 - 由于未经检查的转换,返回类型被删除了!见this equestion
因此filter(containsAnE)
会返回原始Stream
。
原始类型的实例方法也都被删除了,因此collect
方法签名是
Object collect(Collector collector)
这适用于对joining(" ")
参数Collector<CharSequence, ?, String>
进行子类型化。代码编译到目前为止。但返回类型为Object
。
如果您将output
变量的类型更改为Object
Object output = Arrays.stream(splits)
.filter(containsAnE)
.collect(joining(" "));
代码编译,然后正确运行。
这不是意外;为确保预通用代码与新的通用API一起工作,我们做了很多努力。这在2005年非常重要。当然,今天,我们不再有这种担忧。 只是不使用原始类型。 (除非我们必须......在某些用例中...)