2015-05-26 11 views
7

Voglio contare i diversi elementi di un ruscello e mi chiedo il motivo per cuielementi di conteggio di un flusso

Stream<String> stream = Stream.of("a", "b", "a", "c", "c", "a", "a", "d"); 
Map<String, Integer> counter1 = stream.collect(Collectors.toMap(s -> s, 1, Integer::sum)); 

non funziona. Eclipse mi dice

Il metodo toMap (Funzione, Funzione, BinaryOperator) nel tipo I collezionisti non è applicabile per gli argomenti ((S) -> {}, int, Integer :: sum)

A proposito, so che la soluzione:

Map<String, Long> counter2 = stream.collect(Collectors.groupingBy(s -> s, Collectors.counting())); 

Così ho due domande:

  1. Qual è esimo e errore nel mio primo approccio?
  2. Come implementereste un simile contatore?

EDIT: Ho risolto la prima domanda da solo:

Map<String, Integer> counter1 = stream.collect(Collectors.toMap(s -> s, s -> 1, Integer::sum)); 

Java si aspetta una funzione come secondo argomento.

+2

Se hai risolto la domanda da solo, scrivi una risposta invece di modificare la domanda. –

+0

@TagirValeev È solo la prima parte. Una risposta non dovrebbe rispondere alla domanda completa? Voglio anche che la gente non si preoccupi più di dirmi cosa ho fatto di sbagliato. –

+0

http://stackoverflow.com/questions/25441088/group-by-counting-in-java8-stream-api –

risposta

4

Ci sono davvero diversi modi per farlo. Quello che non hai menzionato è .collect(groupingBy(x -> x, summingInt(x -> 1)));

Ci sono alcune differenze nelle prestazioni.

L'approccio n. 1 sarà ottimale se ci sono pochissimi oggetti per secchio. Nel caso ideale di solo 1 oggetto per bucket, si finisce con la mappa finale subito senza la necessità di modificare le voci. Nel caso peggiore di avere un numero molto grande di oggetti ripetuti, dovrà fare un sacco di boxe/unboxing.

L'approccio n. 2 si basa sul collettore counting(), che non specifica esattamente come dovrebbe eseguire il conteggio. L'attuale implementazione inoltra a reducing ma potrebbe cambiare.

L'approccio summingInt si accumulerà il conteggio nel int piuttosto che Integer e quindi non richiede alcun boxing/unboxing. Sarà al suo meglio se gli oggetti ripetono un numero molto grande di volte.

Per quanto riguarda la scelta, è consigliabile codificarlo per chiarezza e ottimizzare quando è necessario. Per me, groupingBy(x->x, counting()) esprime chiaramente l'intento, quindi è quello che preferirei.