如何将 Stream 方法分配给 java 8 中的函数?

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

我有一个案例如下:

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

我有两种情况需要根据具体情况查找最小值或最大值?我如何用函数替换第三行的调用最大值,以便它直接使用 .apply() 方法并执行操作?

我已成功分配 Collection.max 或 Collection 分钟,如下所示:

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

我使用它如下:

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

只使用一个条件可能会更简单:

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();

如果需要,您可以将 min/max 操作存储在单独的 Function 中:

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);

选择使用 min 而不是 max 与仍然使用 max 操作没有什么不同,但顺序相反,因此您可以使用

初始化:

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

实际操作

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

颠倒顺序对性能没有影响。它只是意味着调用 r2.getId().compareTo(r1.getId()) 而不是 r1.getId().compareTo(r2.getId())

另一种选择是

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();

这预计what min and max would do


您可以使用任一变体来创建您的 BiFunction,例如

变体 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();

变体 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();

当然,您也可以忍受代码重复

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();

在任何一种情况下,条件 expComponents[0] == 'M' 仅在创建 BiFunction 时检查一次,并且在调用 mrOrlrOperation.apply(…) 时从不评估。

max是归约运算,那么可以使用泛型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);
...