@Nonnull
    public static <T> AggregateOperation1<T, LongLongAccumulator, Double> averagingLong(
            @Nonnull ToLongFunctionEx<? super T> getLongValueFn
    ) {
        checkSerializable(getLongValueFn, "getLongValueFn");
        // count == accumulator.value1
        // sum == accumulator.value2
        return AggregateOperation
                .withCreate(LongLongAccumulator::new)
                .andAccumulate((LongLongAccumulator a, T i) -> {
                    // a bit faster check than in addExact, specialized for increment
                    if (a.get1() == Long.MAX_VALUE) {
                        throw new ArithmeticException("Counter overflow");
                    }
                    a.set1(a.get1() + 1);
                    a.set2(Math.addExact(a.get2(), getLongValueFn.applyAsLong(i)));
                })
                .andCombine((a1, a2) -> {
                    a1.set1(Math.addExact(a1.get1(), a2.get1()));
                    a1.set2(Math.addExact(a1.get2(), a2.get2()));
                })
                .andDeduct((a1, a2) -> {
                    a1.set1(Math.subtractExact(a1.get1(), a2.get1()));
                    a1.set2(Math.subtractExact(a1.get2(), a2.get2()));
                })
                .andExportFinish(a -> (double) a.get2() / a.get1());
    }
@Test
    public void when_averagingLong_tooManyItems_then_exception() {
        // Given
        AggregateOperation1<Long, LongLongAccumulator, Double> aggrOp = averagingLong(Long::longValue);
        LongLongAccumulator acc = new LongLongAccumulator(Long.MAX_VALUE, 0L);

        // When
        BiConsumerEx<? super LongLongAccumulator, ? super Long> biConsumerEx = aggrOp.accumulateFn();
        assertThrows(ArithmeticException.class, () -> biConsumerEx.accept(acc, 0L));
    }