datto
datto

Reputation: 411

Factorize code where the only differences are Stream reduction operation

I have a bunch of methods where the only difference is a Stream reduction operation :

static Stream<TimeValues> avg(Stream<TimeValues> data, int batchSize) {
    return data
            .collect(SlidingCollector.batch(batchSize))
            .stream()
            .map(tvl -> {
                    OptionalDouble od = tvl.stream()
                    ...
                        .mapToDouble(tv -> tv.doubleValue())
                        .average(); // <-------
                    ...      
            });
}
static Stream<TimeValues> max(Stream<TimeValues> data, int batchSize) {
    return data
            .collect(SlidingCollector.batch(batchSize))
            .stream()
            .map(tvl -> {
                    OptionalDouble od = tvl.stream()
                    ...
                        .mapToDouble(tv -> tv.doubleValue())
                        .max(); // <-------
                    ...      
            });
}

How to factorize this code and have a parametrized reduction operation (min, max, average, sum) ?

Thanks in advance.

Upvotes: 1

Views: 80

Answers (2)

azro
azro

Reputation: 54168

The methods .average and .max are both Function<DoubleStream, OptionalDouble> , you can so store them in this type :

Function<DoubleStream, OptionalDouble> avg = DoubleStream::average; // ie ds -> ds.average()
Function<DoubleStream, OptionalDouble> mx = DoubleStream::max;

The use it as a parameter and use .apply with the DoubleStream as parameter

static Stream<TimeValues> method(Stream<TimeValues> data, int batchSize, 
                                 Function<DoubleStream, OptionalDouble> fct) {
    return data
            .collect(SlidingCollector.batch(batchSize))
            .stream()
            .map(tvl -> {
                OptionalDouble od = fct.apply(tvl.stream().mapToDouble(Number::doubleValue));
            });
}

So the calls will be

Function<DoubleStream, OptionalDouble> avg = ds -> ds.average();
Function<DoubleStream, OptionalDouble> mx = DoubleStream::max;

method(...,10, avg);
method(...,10, mx);

Upvotes: 3

Andreas
Andreas

Reputation: 159135

Both average() and max() are Function<DoubleStream, OptionalDouble> type methods, so:

static Stream<TimeValues> avg(Stream<TimeValues> data, int batchSize) {
    return reduce(data, batchSize, DoubleStream::average);
}

static Stream<TimeValues> max(Stream<TimeValues> data, int batchSize) {
    return reduce(data, batchSize, DoubleStream::max);
}

private static Stream<TimeValues> reduce(Stream<TimeValues> data, int batchSize,
                                         Function<DoubleStream, OptionalDouble> reducer) {
    return data
            .collect(SlidingCollector.batch(batchSize))
            .stream()
            .map(tvl -> {
                    OptionalDouble od = reducer.apply(tvl.stream()
                    ...
                        .mapToDouble(tv -> tv.doubleValue()));
                    ...      
            });
}

Upvotes: 3

Related Questions