Stream工作时没有过滤器(谓词),给它“不兼容的类型”

时间:2015-08-11 16:53:59

标签: java generics java-stream

为什么以下代码仅在过滤谓词行被注释掉时才起作用。使用过滤器行,它会给我这个错误:

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

2 个答案:

答案 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年非常重要。当然,今天,我们不再有这种担忧。 只是不使用原始类型。 (除非我们必须......在某些用例中...)