Как получить среднюю длину слов с помощью выражения Lambda
У меня есть текстовый файл списка слов, я хочу получить минимальные, максимальные и средние длины слов из этого файла.
У меня есть метод потока:
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();
}
}
В моем основном методе тестирования я печатаю max и 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()
);
работает как ожидалось.
Вопросы:
Можно ли получить среднее значение длины слова, как в минуту и макс? В обоих случаях да или нет, как это сделать (только как выражение Лямбды)?
Ответы
Ответ 1
Метод lines()
даст вам поток строк, а не слова. Когда у вас есть Stream
, вызовите flatMap
, чтобы заменить строки словами, предоставив выражение лямбда для разделения слов:
Stream<String> stringStream = reader.lines().flatMap( line ->
Stream.of(line.split("\\s+"))
);
Это исправит вашу реализацию max
и min
. Это также влияет на правильность любого среднего расчета, который вы хотите реализовать.
Чтобы получить среднее значение, вы можете вызвать mapToInt
, чтобы сопоставить поток слов с их длиной (с результатом IntStream
), затем вызовите average
, который возвращает OptionalDouble
.
System.out.println(readWords(filename)
.mapToInt( s -> s.length() ) // or .mapToInt(String::length)
.average()
.getAsDouble());
Ответ 2
Используйте IntSummaryStatistics
, чтобы получить минимальное, максимальное и среднее за один проход.
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());
Ответ 3
На основе официальной документации о сокращения
System.out.println(readWords(filename)
.mapToInt(String::length)
.average()
.getAsDouble()
);
Обратите внимание, что вы можете и, вероятно, должны использовать ссылки на методы, такие как String::length