17

我在玩 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 类型时,有什么方法可以使它工作吗?

在此先感谢,丹尼尔

4

3 回答 3

21

我认为他们正在改变方法

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

于 2013-03-21T20:14:24.470 回答
2

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

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

reduce(T 标识,BinaryOperator<T> 累加器)

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

reduce() 是如何工作的:假设我们有 int 数组流并且我们应用了 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;
    }
}
于 2014-03-21T11:16:41.030 回答
0

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

persons.stream().mapToInt(x->x.getAge()).sum();
于 2015-04-17T02:19:34.497 回答