[英]Stream API map() and filter()
I am trying to learn the Stream API and i came across the below code: 我正在尝试学习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());
}
}
It gives a 它给了一个
symbol "average()"not found error.
符号“average()”未找到错误。
But when I change the sysout with the below it runs fine as expected 但是,当我用下面的更改sysout时,它按预期运行正常
System.out.println(a.stream().filter(i -> i < 10).mapToInt(i -> i).average());
Can someone please explain the difference here? 有人可以解释这里的区别吗?
A Stream<T>
has no average()
method, since the element type T
can be any reference type, which doesn't necessarily have a meaning for calculation of the average of the Stream
elements. Stream<T>
没有average()
方法,因为元素类型T
可以是任何引用类型,其不一定具有计算Stream
元素的平均值的含义。
On the other hand, an IntStream
has an average()
method, since it has int
elements, for which the average operation is well defined. 另一方面,
IntStream
有一个average()
方法,因为它有int
元素,为其定义了平均操作。
Therefore you must convert a Stream<Integer>
to an IntStream
(via mapToInt()
) in order to call average()
. 因此,您必须将
Stream<Integer>
转换为IntStream
(通过mapToInt()
)才能调用average()
。
To explain it a bit more in detail: 更详细地解释一下:
This is giving you a List
of Integer
(the arguments are boxed from int
to Integer
): 这给你一个
Integer
List
(参数从int
加到Integer
):
List <Integer> a = Arrays.asList(2,3,4);
The following statement is converting your List<Integer>
into a Stream<Integer>
以下语句将
List<Integer>
转换为Stream<Integer>
a.stream()
Now filtering still preserves the type Stream<Integer>
, and Stream
doesn't provide a method called average()
(as it can consist of any generic type). 现在,过滤仍保留
Stream<Integer>
类型, Stream
不提供名为average()
的方法(因为它可以包含任何泛型类型)。
Calling mapToInt(i -> i)
converts your Stream<Integer>
into an IntStream
, which does have a method called average()
. 调用
mapToInt(i -> i)
将Stream<Integer>
转换为IntStream
,它有一个名为average()
的方法。 Note that i -> i
is a ToIntFunction<Integer>
, which converts an Integer
back to an int
due to auto-unboxing. 请注意,
i -> i
是ToIntFunction<Integer>
,它会因自动取消装箱而将Integer
转换回int
。
Another way to fix that would be 解决这个问题的另一种方法是
System.out.println(IntStream.of(2,3,4).filter(i -> i < 10).average());
Expressing calculations as chains is convenient, but sometimes it hides type information that might be useful to understanding what's going on. 将计算表示为链是很方便的,但有时它会隐藏可能有助于理解正在发生的事情的类型信息。 Try rewriting
尝试重写
List <Integer> a = Arrays.asList(2,3,4);
System.out.println(a.stream().filter(i -> i < 10).average());
where every result has an explicit type (your IDE should help you.) Then you get: 每个结果都有一个显式类型(你的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();
When you write it this way, you'll see that you're trying to invoke a nonexistent method on Stream<Integer>
. 当您以这种方式编写它时,您将看到您尝试在
Stream<Integer>
上调用不存在的方法。 You want an IntStream
, which does have an average()
method. 你想要一个
IntStream
,它有一个average()
方法。 So you can rewrite as: 所以你可以重写为:
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();
and everything is good. 一切都很好。 Then you can roll it back up with chaining and implicit lambdas:
然后你可以用链接和隐式lambda来回滚它:
double average = a.stream()
.mapToInt(i -> i)
.filter(i -> i<10)
.average();
The lesson here is: when you're confused, unroll complex expressions into simpler ones with manifest types. 这里的教训是:当您感到困惑时,将复杂的表达式展开为具有清单类型的简单表达式。 Often, this helps you spot the problem immediately;
通常,这可以帮助您立即发现问题; if not, it generally results in a more informative compiler error.
如果不是,它通常会导致更具信息性的编译器错误。
(If you use IntelliJ, you can use the "extract variable" refactor to pull a subexpression into a local variable with its inferred type.) (如果使用IntelliJ,则可以使用“提取变量”重构将子表达式拉入具有推断类型的局部变量。)
Arrays.asList(2,3,4).stream()
would given you Stream<Integer>
which is of type Stream and it does not have any average() method, hence the error. Arrays.asList(2,3,4).stream()
会给你Stream<Integer>
,它是Stream类型,它没有任何average()方法,因此错误。
Arrays.asList(2,3,4).mapToInt()
would return IntStream which is one of the four primitive specialized classes provided by Stream API and it has average() method, hence it works. Arrays.asList(2,3,4).mapToInt()
将返回IntStream,它是Stream API提供的四个原始专用类之一,它具有average()方法,因此它可以工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.