Подтвердить что ты не робот

Java 8 Lambdas: сопоставление потока для ввода Integer, а затем вызов sum() не будет компилироваться

Я играл с ямба-выражениями Java8. В качестве примера я попытался подвести итоги людям, содержащимся в списке:

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?

Спасибо заранее, Daniel

4b9b3361

Ответ 1

Я думаю, что они меняют метод

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, они хотели бы услышать реальный опыт в мире.

Ответ 2

Они не меняют методы, оба из них доступны там, где map() - это обобщенный метод, который возвращает Stream, и они разделили int, long, double Stream на отдельный метод как mapToInt(), mapToLong() и mapToDouble().

Да, вы можете использовать метод reduce()

уменьшить (T identity, BinaryOperator <T> аккумулятор)

Выполняет сокращение элементов этого потока, используя ассоциативную функцию накопления, и возвращает необязательное описание уменьшенного значения, если оно есть.

Как работает сокращение(): предположим, что у нас есть поток массива int, и мы применяем функцию сокращения

уменьшить (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;
    }
}

Ответ 3

Чтобы добавить ответ bayou.io, я предпочитаю выражение лямбда вместо ссылки на метод.

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