我正在尝试学习Stream API,我遇到了以下代码:
public class Test{
public static void main (String[] args)
{
List <Integer> a = Arrays.asList(2,3,4);
System.out.println(a.stream().filter(i -> i < 10).average());
}
}
它给出了
符号&#34;平均值()&#34;未找到错误。
但是当我用下面的内容更改sysout时,它按预期运行正常
System.out.println(a.stream().filter(i -> i < 10).mapToInt(i -> i).average());
有人可以在这里解释一下这个区别吗?
答案 0 :(得分:9)
Stream<T>
没有average()
方法,因为元素类型T
可以是任何引用类型,它不一定具有计算平均值的含义。 Stream
元素。
另一方面,IntStream
有一个average()
方法,因为它有int
个元素,平均操作定义明确。
因此,您必须将Stream<Integer>
转换为IntStream
(通过mapToInt()
)才能致电average()
。
答案 1 :(得分:3)
更详细地解释一下:
这会为您提供List
Integer
(参数从int
加载到Integer
):
List <Integer> a = Arrays.asList(2,3,4);
以下声明将您的List<Integer>
转换为Stream<Integer>
a.stream()
现在过滤仍保留类型Stream<Integer>
,Stream
不提供名为average()
的方法(因为它可以包含任何泛型类型)。
致电mapToInt(i -> i)
会将您的Stream<Integer>
转换为IntStream
,其中有一个名为average()
的方法。请注意,i -> i
是ToIntFunction<Integer>
,由于自动取消装箱,会将Integer
转换回int
。
另一种解决方法是
System.out.println(IntStream.of(2,3,4).filter(i -> i < 10).average());
答案 2 :(得分:2)
将计算表示为链条很方便,但有时会隐藏可能有助于了解正在进行的内容的类型信息。尝试重写
List <Integer> a = Arrays.asList(2,3,4);
System.out.println(a.stream().filter(i -> i < 10).average());
每个结果都有一个显式类型(你的IDE应该帮助你。)然后你得到:
List <Integer> a = Arrays.asList(2,3,4);
Stream<Integer> s1 = a.stream();
Stream<Integer> s2 = s1.filter((Integer i) -> i < 10);
double average = s2.average();
当您以这种方式编写时,您会发现您正试图在Stream<Integer>
上调用不存在的方法。您需要一个IntStream
,它有一个average()
方法。所以你可以改写为:
List<Integer> a = Arrays.asList(2,3,4);
Stream<Integer> s1 = a.stream();
IntStream s2 = s1.mapToInt((Integer i) -> i);
IntStream s3 = s2.filter((Integer i) -> i < 10);
double average = s3.average();
一切都很好。然后你可以用链接和隐式lambda来回滚它:
double average = a.stream()
.mapToInt(i -> i)
.filter(i -> i<10)
.average();
这里的教训是:当您感到困惑时,将复杂的表达式展开为具有清单类型的简单表达式。通常,这可以帮助您立即发现问题;如果不是,它通常会导致更具信息性的编译器错误。
(如果使用IntelliJ,则可以使用&#34;提取变量&#34;重构将子表达式拉入具有推断类型的局部变量。)
答案 3 :(得分:1)
Arrays.asList(2,3,4).stream()
会给你Stream<Integer>
这是Stream类型的,它没有任何average()方法,因此错误。
Arrays.asList(2,3,4).mapToInt()
将返回IntStream,这是Stream API提供的四个原始专用类之一,它有average()方法,因此它可以工作。