Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get words average length using Lambda Expression

I have a word list text file, I want to get min, max and average word lengths from that file.

I have a stream method:

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

In my main method for testing I'm printing max and 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()
);

it works as expected.

Questions:
Is it possible to get the average of the word length like I did in min and max? In both case yes or no, how to do that (only as Lambda Expression)?

like image 514
Maytham Avatar asked Sep 11 '15 23:09

Maytham


2 Answers

The lines() method will get you a stream of the lines, not the words. Once you have the Stream, call flatMap to replace the lines with the words, supplying the lambda expression to split out the words:

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

This will correct your implementation of max and min. It also affects the correctness of any average calculation you wish to implement.

To obtain the average, you can call mapToInt to map the stream of words to their lengths (yielding an IntStream), then call average, which returns an OptionalDouble.

System.out.println(readWords(filename)
    .mapToInt( s -> s.length() )  // or .mapToInt(String::length)
    .average()
    .getAsDouble());
like image 128
rgettman Avatar answered Oct 22 '22 22:10

rgettman


Use IntSummaryStatistics to get the min, max and average in one pass.

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());
like image 33
David Conrad Avatar answered Oct 22 '22 22:10

David Conrad