如何识别原始类型

how to recognize raw type

我有这个练习:

List<Integer> iList = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
Predicate<Integer> p = x -> x%2 == 0; 
List newList = iList.stream()
                    .filter(p)
                    .filter(x -> x>3)
                    .collect(Collectors.toList()); 

System.out.println(newList);

在我看来,newList 是原始类型而不是泛型,因为它被初始化为 List newList 而不是 List<Integer>。 这个练习怎么可能有正常的结果而不是编译错误?

如果我写:

List iList = Arrays.asList(1,2,3,4,5,6,7);
iList.stream()
     .filter(x -> x%2==0)
     .filter(x -> x>3)
     .collect(Collectors.toList());

它不编译。为什么在第一种情况下代码可以编译?

你是对的,这是原始类型:

List newList = iList.stream().filter(p).filter(x>x>3).collect(Collectors.toList()); 
System.out.println(newList);

然而,原始类型是完全合法的,不会导致编译错误。它们只是非常糟糕的使用习惯。您的第二个代码片段证明了这一点:

List iList= Arrays.asList(1,2,3,4,5,6,7);
iList.stream().filter(x -> x%2 ==0).filter(x -> x>3).collect(Collectors.toList());

这里因为 iList 是原始类型,编译器不知道 iList 包含 int 并将它们视为对象,所以你不能使用 % 运算符在这里。我得到的实际错误是:

bad operand types for binary operator '%'
  first type:  Object
  second type: int

bad operand types for binary operator '>'
  first type:  Object
  second type: int

请注意,这会忽略您的 lambda 表达式中的语法错误。正确的语法是 x -> x > 3 而不是 x>x>3

Stream 将原始对象序列识别为简单的 Stream<Object>。如果您想将其视为 Stream<Integer>,则必须使用 Stream::mapToInt 显式声明此事实并将整个 Stream:

装箱
List<Integer> newList = iList.stream()                    // Stream
     .mapToInt(obj -> Integer.valueOf(obj.toString()))    // IntStream
     .boxed()                                             // Stream<Integer>
     .filter(x -> x % 2 == 0) 
     .filter(x -> x > 3)
     .collect(Collectors.toList());                       // List<Integer>

在第一种情况下,显然 Stream 将 self 声明为 Stream<Integer>,因为它是从 List<Integer>.

创建的

请注意,您的 lambda 语法错误,应该是 x -> x % 2 == 0 和箭头 ->

List newList 只是 return 类型的流链。

实际上您正在使用 List<Integer> iList 这不是原始类型。因此没有编译错误