2015-09-11 16 views
10

Ho un file di testo elenco di parole, voglio ottenere lunghezze di parole min, max e medie da quel file.Come ottenere la lunghezza media delle parole utilizzando Lambda Expression

Ho un metodo stream:

public static Stream<String> readWords(String filename) { 
    try { 
     BufferedReader reader = new BufferedReader(new FileReader(filename)); 
     Stream<String> stringStream = reader.lines(); 
     return stringStream; 
    } catch (IOException exn) { 
     return Stream.<String>empty(); 
    } 
} 

Nel mio metodo principale per la prova che sto stampando max e min

System.out.println(readWords(filename) 
     .min(Comparator.comparing(s -> s.length())) 
     .get() 
     .length() 
); 
System.out.println(readWords(filename) 
     .max(Comparator.comparing(s -> s.length())) 
     .get() 
     .length() 
); 

funziona come previsto.

Domande:
E 'possibile ottenere la media della lunghezza di parola come ho fatto in min e max? In entrambi i casi si o no, come farlo (solo come espressione Lambda)?

+0

è possibile utilizzare .reduce (0, (i, c) -> c + i.length()) e dividerlo per numero di righe. –

+0

suggerimento: se il tuo file è davvero grande e ha un sacco di righe utilizzare raccogliere invece di ridurre –

+0

@JoshuaK grazie anche per il tuo contributo, ho trovato la risposta sotto –

risposta

13

Il metodo lines() consente di ottenere un flusso delle linee, non le parole. Una volta ottenuto il Stream, chiamare flatMap di sostituire le linee con le parole, fornendo l'espressione lambda per dividere le parole:

Stream<String> stringStream = reader.lines().flatMap(line -> 
    Stream.of(line.split("\\s+")) 
); 

Questo correggerà l'implementazione di max e min. Influisce anche sulla correttezza di qualsiasi calcolo medio che desideri implementare.

Per ottenere la media, è possibile chiamare mapToInt per mappare il flusso di parole per le loro lunghezze (ottenendo un IntStream), quindi chiamare average, che restituisce un OptionalDouble.

System.out.println(readWords(filename) 
    .mapToInt(s -> s.length()) // or .mapToInt(String::length) 
    .average() 
    .getAsDouble()); 
+0

Perché dovrebbe essere 11? –

+0

Funziona su, e mi piace il tuo contributo per .flatMap ecc. –

+3

come su 'summaryStatistics()' - https://docs.oracle.com/javase/8/docs/api/java/util/stream/IntStream .html # summaryStatistics-- – ZhongYu

6

Sulla base di documentazione ufficiale circa reductions

System.out.println(readWords(filename) 
       .mapToInt(String::length) 
       .average() 
       .getAsDouble() 
); 

noti che è possibile e, probabilmente, dovrebbe utilizzare il metodo riferimenti come String::length

+0

il tuo codice funziona troppo alto Ho selezionato l'altra risposta a causa dell'ingresso Stream, la tua risposta è valida pure. –

+0

Ho svalutato la risposta di rgettman per lo stesso motivo :-) Grazie –

7

Usa IntSummaryStatistics per ottenere il minimo, massimo e medio in un solo passaggio.

IntSummaryStatistics summary = readWords(filename) 
    .collect(Collectors.summarizingInt(String::length)); 
System.out.format("min = %d, max = %d, average = %.2f%n", 
    summary.getMin(), summary.getMax(), summary.getAverage()); 
+1

Grazie anche a questo funziona e basta testarlo. pollice su –

Problemi correlati