Ajeetkumar
Ajeetkumar

Reputation: 1329

How to assign Stream method to a Function in java 8?

I have a case as below:

RowDataSet rdsHavingMaxNumericValue = dataList.stream()
                    .filter(r -> r.getLong(NUMERIC_VALUE) != null)
                    .max((r1, r2) -> r1.getId().compareTo(r2.getId()))
                    .get();

I've two cases where I need to find either min or max depending on a case? how can i replace the call max at third line by a Function so that it direcly uses .apply() method and performs the operation?

I'v successfully assigned Collection.max or Collection min as below:

 BiFunction<List<RowDataSet>, Comparator<RowDataSet>, RowDataSet> mrOrlrOperation = expComponents[0] == 'M' ? Collections::max : Collections::min;

and i use it as below:

RowDataSet rds = mrOrlrOperation.apply(dataList, <some comparator>);

Upvotes: 3

Views: 240

Answers (3)

Jean-Baptiste Yun&#232;s
Jean-Baptiste Yun&#232;s

Reputation: 36401

max is a reducing operation, then you can use the generic reduce:

public void reducing(BiOperator<...> myFunction) {
    RowDataSet rdsHavingMaxNumericValue = dataList.stream()
                .filter(r -> r.getLong(NUMERIC_VALUE) != null)
                .reduce((r1, r2) -> myFunction.apply(r1,r2))
                .get();
}
...
reducing(Integer::max);
...

Upvotes: 0

Holger
Holger

Reputation: 298153

The choice to use min instead of max is not different to still using the max operation, but with a reversed order, so you could use

Initialization:

Comparator<RowDataSet> c = Comparator.comparingLong(RowDataSet::getId);
if(expComponents[0] != 'M') c = c.reversed();

Actual operation

RowDataSet rdsHavingMaxNumericValue =
    dataList.stream()
            .filter(r -> r.getLong(NUMERIC_VALUE) != null)
            .max(c)
            .get();

Reversing the order has no performance impact. It just implies calling r2.getId().compareTo(r1.getId()) instead of r1.getId().compareTo(r2.getId())

An alternative would be

Comparator<RowDataSet> c = Comparator.comparingLong(RowDataSet::getId);
BinaryOperator<RowDataSet> op = expComponents[0] == 'M'?
                                BinaryOperator.maxBy(c): BinaryOperator.minBy(c);

RowDataSet rdsHavingMaxNumericValue =
    dataList.stream()
            .filter(r -> r.getLong(NUMERIC_VALUE) != null)
            .reduce(op)
            .get();

This anticipates what min and max would do


You can use either variant to create your BiFunction, e.g.

Variant 1:

Function<Comparator<RowDataSet>, Comparator<RowDataSet>>
    maxOrMin = expComponents[0] == 'M'? Function.identity(): Comparator::reversed;

BiFunction<List<RowDataSet>, Comparator<RowDataSet>, RowDataSet> mrOrlrOperation
    = (dataList, comparator) -> dataList.stream()
                                        .filter(r -> r.getLong(NUMERIC_VALUE) != null)
                                        .max(maxOrMin.apply(comparator))
                                        .get();

Variant 2:

Function<Comparator<RowDataSet>, BinaryOperator<RowDataSet>>
    maxOrMin = expComponents[0] == 'M'? BinaryOperator::maxBy: BinaryOperator::minBy;

BiFunction<List<RowDataSet>, Comparator<RowDataSet>, RowDataSet> mrOrlrOperation
    = (dataList, comparator) -> dataList.stream()
                                        .filter(r -> r.getLong(NUMERIC_VALUE) != null)
                                        .reduce(maxOrMin.apply(comparator))
                                        .get();

Of course, you could also live with a code duplication

BiFunction<List<RowDataSet>, Comparator<RowDataSet>, RowDataSet> mrOrlrOperation
    = expComponents[0] == 'M'?
        (dataList, comparator) -> dataList.stream()
                                          .filter(r -> r.getLong(NUMERIC_VALUE) != null)
                                          .max(comparator)
                                          .get():
        (dataList, comparator) -> dataList.stream()
                                          .filter(r -> r.getLong(NUMERIC_VALUE) != null)
                                          .min(comparator)
                                          .get();

In either case, the condition expComponents[0] == 'M' is checked only once when the BiFunction is created and never evaluated when mrOrlrOperation.apply(…) is invoked.

Upvotes: 5

assylias
assylias

Reputation: 328608

It would probably be simpler to just use a condition:

Stream<?> stream = dataList.stream()
                           .filter(r -> r.getLong(NUMERIC_VALUE) != null);
Comparator<RowDataSet> c = Comparator.comparingLong(RowDataSet::getId);
RowDataSet rdsHavingMaxNumericValue =
               expComponents[0] == 'M' ? stream.max(c).get() : stream.min(c).get();

You can store the min/max operation in a separate Function if you want:

BiFunction<Stream<RowDataSet>, Comparator<RowDataSet>, RowDataSet>> operation = 
             expComponents[0] == 'M' ? (s, c) -> s.max(c).get() : (s, c) -> s.min(c).get();

RowDataSet rdsHavingMaxNumericValue = operation.apply(stream, c);

Upvotes: 3

Related Questions