Java 8 Lambdas:将流映射到整数类型,然后调用 sum() 不会编译



我正在使用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类型时,是否有任何方法可以使此工作?

Thanks in advance

我想他们正在改变方法

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邮件列表,他们想听听真实世界的经验。

它们没有改变方法,它们都是可用的,因为map()是一个返回Stream的广义方法,并且它们将int, long, double Stream分离为单独的方法,例如mapToInt(), mapToLong()和mapToDouble()。

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

reduce(T identity, BinaryOperator<</strong>

使用关联累加函数对该流的元素执行约简操作,如果有,则返回描述约简值的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;
    }
}

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

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

最新更新