流API map()和filter()

时间:2018-03-04 06:34:01

标签: java lambda java-8 java-stream

我正在尝试学习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());

有人可以在这里解释一下这个区别吗?

4 个答案:

答案 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 -> iToIntFunction<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()方法,因此它可以工作。