2013-03-21 12 views
13

Grałem z wyrażeń lambda Java8. Jako przykład mogę potem próbował podsumować wieki osoby znajdujące się na liście:Java 8 Lambdas: Mapowanie strumienia do typu Integer, a następnie wywoływanie sum() nie będzie kompilować

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; 
    } 
} 

Kiedy próbuję skompilować ten fragment z następującym java kompilatora:

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) 

otrzymuję następujący błąd kompilacji :

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

Ale jeśli zmienić wartość zwracaną przez metodę getAge() z Integer do int, uzyskać oczekiwany rezultat. Czasem jednak nie jest możliwa lub pożądana zmiana sygnatur w locie. Czy istnieje sposób, aby to działało, gdy getAge() zwraca typ liczb całkowitych?

Dzięki z góry, Daniel

+0

'zmniejszyć()' powinno działać też - 'map (Person :: getAge) .reduce (0, Integer :: suma)' – ZhongYu

Odpowiedz

2

nie są one zmianę metody, oba są dostępne w którym jako mapie() jest uogólniona metoda wraca strumień, i oddzieli int długi, podwójny strumień do oddzielnego sposobem, takim jak mapToInt(), mapToLong() i mapToDouble().

Tak, można użyć zmniejszyć() metoda

zmniejszyć (T tożsamość, BinaryOperator < T> akumulator)

Wykonuje redukcję na elementach tego strumienia, używając asocjacyjną funkcję akumulacji, i zwraca opcjonalny opis zmniejszonej wartości, jeśli taka istnieje.

Jak zmniejszyć() działa: załóżmy, że mamy strumień int tablicy i możemy zastosować funkcję zmniejszenia

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

na liście liczb, takich jak 1, 2, 3, 4 i 5, ziarno 0 jest dodawane do 1, a wynik (1) jest przechowywany jako wartość skumulowana, która następnie służy jako wartość lewej ręki i służy jako kolejny numer w strumieniu (1 + 2). Wynik (3) jest przechowywany jako wartość skumulowana i używany przy następnym dodaniu (3 + 3).Wynik (6) jest przechowywany i wykorzystywany przy kolejnym dodawaniu (6 + 4), a wynik jest używany przy ostatecznym dodaniu (10 + 5), co daje końcowy wynik 15.

Twój przykład będzie wyglądał jak :

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; 
    } 
} 
0

Aby dodać bayou.io odpowiedź, wolę wyrażenia lambda zamiast Referencyjna metoda.

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