Collectors.averagingInt - это скользящее среднее или все предыдущие числа хранятся в памяти? - PullRequest
0 голосов
/ 21 апреля 2020

В следующем коде усреднение работает как скользящее среднее или сохраняет в памяти все предыдущие целые числа и каждый раз пересчитывает среднее? Я хочу получить скользящее среднее, поскольку число целых чисел в файле может быть очень большим (поэтому я не хочу, чтобы все они были сохранены в памяти), но другой разработчик указал, что четвертая строка может фактически попытаться сохранить все целые числа в памяти и пересчитывать среднее значение каждый раз. Какой из них правильный? Спасибо

return Files.readAllLines(Paths.get(fileName)).stream()
        .flatMap(n -> Arrays.stream(n.split(" ")))
        .map(Integer::valueOf)
        .collect(Collectors.averagingInt(Integer::intValue));

Ответы [ 2 ]

4 голосов
/ 21 апреля 2020

Коллектор усреднения не должен хранить все числа, которые он усредняет, в памяти: все, что ему нужно для отслеживания, - это сумма и количество элементов, которые затем делятся в конце, чтобы получить среднее значение.

Таким образом, не имеет значения, сколько вещей читается из файла: пространство, используемое для вычисления среднего, является постоянным.


В есть бит Java 3-е издание, на стр. 214, где говорится, что вы должны использовать только определенные коллекторы в качестве нижестоящих коллекторов - Collectors.averagingInt является одним из таких коллекторов. Вам не нужно использовать эти коллекторы как «первичные» (если это правильный термин) коллекторы, потому что те же функции доступны непосредственно в API потока.

Более правильный способ - использовать IntStream , который имеет average() метод:

return Files.readAllLines(Paths.get(fileName)).stream()
        .flatMap(n -> Arrays.stream(n.split(" ")))
        .mapToInt(Integer::parseInt)
        .average()   // Returns an OptionalDouble
        .orElse(0);  // averagingInt returns 0 if the stream is empty.
0 голосов
/ 21 апреля 2020

Прежде всего, вы можете переписать это выражение без использования .map следующим образом:

return Files.readAllLines(Paths.get(fileName)).stream()
        .flatMap(n -> Arrays.stream(n.split(" ")))
        .collect(Collectors.averagingInt(Integer::parseInt));

Демо:

import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        double avg = Stream.of("10 20 30 40 50").flatMap(n -> Arrays.stream(n.split(" ")))
                .collect(Collectors.averagingInt(Integer::parseInt));
        System.out.println("Average = " + avg);
    }
}

Выход :

Average = 30.0

Он вычисляет среднее значение массива целочисленных строк, полученных из split(" "), и сохраняет его в памяти.

...