2013-03-21 2 views
13

Stavo giocando con espressioni lambda Java8. Per fare un esempio ho poi cercato di riassumere i secoli persone contenute in un elenco:Java 8 Lambdas: Mappare un flusso per digitare Integer e quindi chiamare sum() non verrà compilato

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

Quando provo a compilare questo frammento di codice con il seguente compilatore 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) 

ottengo il seguente errore di compilazione :

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

Ma se cambio il valore di ritorno del metodo getAge() da Integer a int, ottengo il risultato atteso. Ma a volte non è possibile o desiderato cambiare le firme al volo. C'è un modo per farlo funzionare quando getAge() restituisce un tipo Integer?

Grazie in anticipo, Daniel

+0

'riduci()' dovrebbe funzionare anche - 'map (Person :: getAge) .reduce (0, Integer :: sum)' – ZhongYu

risposta

16

penso che stanno cambiando il metodo di

IntStream map(ToIntFunction<? super T> mapper) 

a

IntStream mapToInt(ToIntFunction<? super T> mapper) 

allora il vostro

persons.stream().mapToInt(Person::getAge).sum() 

volontà alw lavoro, sia getAge() restituisce int o Integer.

Vedi questa discussione: http://mail.openjdk.java.net/pipermail/lambda-libs-spec-experts/2013-March/001480.html

BTW potete inviare le vostre domande a mailing list lambda-dev, vorrebbero ascoltare esperienze del mondo reale.

2

Essi non cambiano i metodi, sono entrambi disponibili dove come mappa() è un metodo generalizzato che restituisce Stream, e hanno separato l'int, lungo, doppio flusso in modo separato come mapToInt(), mapToLong() e mapToDouble().

Sì, è possibile utilizzare ridurre() metodo

ridurre (T identità, BinaryOperator < T> accumulatore)

Esegue una riduzione sugli elementi di questo flusso, utilizzando una funzione di accumulazione associativa, e restituisce un Facoltativo che descrive il valore ridotto, se presente.

Come ridurre() funziona: supponiamo di avere flusso di int matrice e applichiamo la funzione di ridurre

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

In un elenco di numeri interi tali da 1, 2, 3, 4, e 5, il seme 0 viene aggiunto a 1 e il risultato (1) viene memorizzato come valore accumulato, che funge quindi da valore di mano sinistra oltre a servire come numero successivo nello stream (1 + 2). Il risultato (3) viene memorizzato come valore accumulato e utilizzato nell'aggiunta successiva (3 + 3).Il risultato (6) viene memorizzato e utilizzato nell'addizione successiva (6 + 4) e il risultato viene utilizzato nell'aggiunta finale (10 + 5), ottenendo il risultato finale 15.

Quindi il tuo esempio sarà simile :

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

Per aggiungere risposta bayou.io, preferisco l'espressione lambda anziché il metodo di riferimento.

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