Потоковая группировка значений

Есть ли нетерминальная версия groupingBy или какой-то другой аккуратный способ для потоковой передачи в результате записи / значения карты?

Я чувствую, что хочу просмотреть значения после groupingBy но лучшее, что я мог придумать, это не красиво:

    StreamEx.ofValues(
            StreamEx.of(0, 1, 2, 4).groupingBy(i -> i % 2)
    ).mapToInt(ii -> IntStreamEx.of(ii).sum())
    // RESULT: [6, 1]

2 ответа

Решение

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

Таким образом, вероятно, предпочтительнее использовать временную структуру данных для хранения количества четных и нечетных значений, которое в этом случае будет Map<Integer, Integer> или даже Map<Boolean, Integer> (где, например, ключ будет true для четных значений и false для нечетных значений, используя Collectors.partitioningBy).


Обратите внимание, что вам не нужно использовать библиотеку StreamEx здесь. Вы можете сделать это напрямую через Stream API:

public static void main(String[] args) {
    Map<Integer, Integer> map =
      Stream.of(0, 1, 2, 4)
            .collect(Collectors.groupingBy(
               i -> i % 2,
               Collectors.summingInt(i -> i)
            ));

    Stream<Integer> stream = map.values().stream();
}

summingInt вероятно, лучшее решение для этого конкретного вопроса.

Я полагаю, я упростил проблему, используя в своем примере целые числа. Моя настоящая проблема заключалась в объединении объектов, а не значений int. я нашел collectingAndThen быть весьма полезным. Это работает так:

Function<List<Integer>, Integer> merge = ii -> ii.stream().mapToInt(i -> i).sum();
Stream.of(0, 1, 2, 4).collect(groupingBy(i -> i % 2, collectingAndThen(toList(), merge))).values();
Другие вопросы по тегам