Java 8 Lambdas:将Stream映射到Integer类型然后调用sum()将无法编译

时间:2013-03-21 19:54:25

标签: java collections lambda java-8

我正在玩Java8 lambda表达式。作为一个例子,我然后尝试总结列表中包含的年龄:

import java.util.Arrays;
import java.util.List;

public class Person {
    public static void main(String[] args) {
        List<Person> persons = Arrays.asList(new Person("FooBar", 12), new Person("BarFoo", 16));
        Integer sumOfAges = persons.stream().map(Person::getAge).sum();
        System.out.println("summedUpAges: " + sumOfAges);
    }

    private final String name;
    private final Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }
}

当我尝试使用以下java编译器编译此代码段时:

openjdk version "1.8.0-ea"
OpenJDK Runtime Environment (build 1.8.0-ea-lambda-night
OpenJDK 64-Bit Server VM (build 25.0-b21, mixed mode)

我收到以下编译错误:

java: cannot find symbol
  symbol:   method sum()
  location: interface java.util.stream.Stream<java.lang.Integer>

但是如果我将getAge()方法的返回值从Integer更改为int,我会得到预期的结果。但有时候不可能或不希望在飞行中更改签名。当getAge()返回一个Integer类型时,有没有办法让它工作?

提前致谢, 丹尼尔

3 个答案:

答案 0 :(得分:17)

我认为他们正在改变方法

IntStream map(ToIntFunction<? super T> mapper)

IntStream mapToInt(ToIntFunction<? super T> mapper)

然后你的

persons.stream().mapToInt(Person::getAge).sum()
无论getAge()int还是Integer

始终有效。

请参阅此主题:http://mail.openjdk.java.net/pipermail/lambda-libs-spec-experts/2013-March/001480.html

顺便说一句,你可以将你的问题发布到lambda-dev邮件列表,他们希望听到真实世界的经历。

答案 1 :(得分:2)

他们没有改变方法,两者都可用,因为 map ()是一个返回Stream的通用方法,他们将int,long,double Stream分成单独的方法,如as mapToInt (), mapToLong ()和 mapToDouble ()。

是的,您可以使用reduce()方法

reduce(T identity,BinaryOperator&lt; T&gt; accumulator)

使用关联累加函数对此流的元素执行减少,并返回描述减少值的Optional(如果有)。

reduce()如何工作:假设我们有int数组流并且我们应用reduce函数

  

reduce(0,(l,r) - > l + r)

在诸如1,2,3,4和5的整数列表中,种子0被添加到1,结果(1)被存储为累积值,然后作为左手值除了作为流中的下一个数字(1 + 2)。结果(3)作为累计值存储并用于下一次加法(3 + 3)。结果(6)存储并用于下一次加法(6 + 4),结果用于最终加法(10 + 5),得到最终结果15。

所以你的例子看起来像:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class Person {

    public static void main(String[] args) {
        List<Person> persons = Arrays.asList(new Person("FooBar", 12), new Person("BarFoo", 16));
        Stream<Integer> stream = persons.stream().map(x -> x.getAge());
        int sum = stream.reduce(0, (l, r) -> l + r);
        System.out.println(sum);

    }

    private final String name;
    private final Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }
}

答案 2 :(得分:0)

要添加bayou.io回答,我更喜欢lambda表达式而不是方法引用。

persons.stream().mapToInt(x->x.getAge()).sum();