我有这个练习:
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());
它不能编译。为什么在第一种情况下代码会编译?
答案 0 :(得分:4)
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
很明显将自己声明为Stream<Integer>
,因为它是根据List<Integer>
创建的。
请注意,lambda的语法错误,应为x -> x % 2 == 0
,带有箭头->
。
答案 1 :(得分:2)
您是正确的,这是原始类型:
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
并将它们视为对象,因此您不能使用{{1} }运算子。我得到的实际错误是:
%
请注意,这将忽略lambda中的语法错误。正确的语法是bad operand types for binary operator '%'
first type: Object
second type: int
bad operand types for binary operator '>'
first type: Object
second type: int
而不是x -> x > 3
答案 2 :(得分:2)
List newList
只是流链的返回类型。
实际上,您正在使用非原始类型的List<Integer> iList
。因此没有编译错误