在Java8中是否有一种优雅的方法来应用过滤器数组?

在Java8中是否有一种优雅的方法来应用过滤器数组?,java,lambda,java-8,java-stream,reduce,Java,Lambda,Java 8,Java Stream,Reduce,有没有一种方法可以使用reduce或类似的方法将过滤器数组应用于对象数组 现在,我有这个: private void applyManyFilters(long[] initialData, LongPredicate... filters) { LongStream stream = Arrays.stream(initialData); for (LongPredicate filter : filters) { stream = stream.filter(fi

有没有一种方法可以使用
reduce
或类似的方法将过滤器数组应用于对象数组

现在,我有这个:

private void applyManyFilters(long[] initialData, LongPredicate... filters) {
    LongStream stream = Arrays.stream(initialData);
    for (LongPredicate filter : filters) {
      stream = stream.filter(filter);
    }
    long[] dataToUse = stream.toArray();

    // Use filtered data
}
更优雅的解决方案如下所示:

private void applyManyFilters(long[] initialData, LongPredicate... filters) {
    long[] dataToUse = Arrays.stream(filters).reduce(Arrays.stream(initialData), (a, b) -> a.filter(b)).toArray();

    // Use filtered data here
}
当然,上面的示例无法编译,因为
reduce
的两个参数都需要是
longdpredicate
,而不是
LongStream
。我很好奇上面的代码是否可以写成一行


(顺便说一句,这是一个关于Java 8如何工作的问题,而不是一个关于风格的问题。我确实同意单线方法的可读性不如循环。)

我相信这就是您想要的:

private void applyManyFilters(long[] initialData, LongPredicate... filters) {
    long[] dataToUse = Arrays.stream(initialData)
                             .filter(v -> Arrays.stream(filters)
                                                .allMatch(f -> f.test(v)))
                             .toArray();
    // Use filtered data
}

更新

合并其他两个答案,还可以创建一个用于组合过滤器数组的辅助方法。您可以在helper类中使其成为一个很好的实用方法,以便在代码中的任何地方重用,同时还可以重写其他谓词(
BiPredicate
DoublePredicate
IntPredicate
Predicate


使用
reduce
的解决方案是使用
LongPredicate::and
将谓词简化为单个谓词,如下所示:

//prints 6
public static void main(String[] args) {
    applyManyFilters(new long[]{1, 2, 3, 4, 5, 6}, l -> l % 2 == 0, l -> l % 3 == 0);
}

private static void applyManyFilters(long[] initialData, LongPredicate... filters) {
    Arrays.stream(initialData).filter(
            Arrays.stream(filters).reduce(l -> true, LongPredicate::and)
    ).forEach(System.out::println);
}

要继续回答@Andreas发布的问题,您可以将其设置为静态通用函数,以便更易于重用:

public static <T> Stream<T> applyManyFilters(Stream<T> data, Predicate<T>... filters) {
    return data.filter(d -> Arrays.stream(filters).allMatch(f -> f.test(d)));
}
publicstaticstreamapplymanyfilters(流数据、谓词…过滤器){
返回data.filter(d->Arrays.stream(filters).allMatch(f->f.test(d));
}

检查此答案将您的答案中使用
reduce(LongPredicate::and)
的想法添加到,但作为可重用的帮助器方法。将您的答案中使用可重用的帮助器方法的想法添加到,但该方法返回组合谓词,因此它的使用更像流。参见when
long[]initialData
流式传输它是自动装箱到
Long
对象的,使用
LongPredicate
Predicate
有什么好处吗?如果不是这样的话,使用通用版本将大大简化代码imo@flkes使用
LongPredicate
的全部目的是在上面的代码中不装箱,例如,第一个示例中的
v
和第二个示例中的
x
都是
long
,而不是
long
。您认为装箱发生在哪里?不
数组。流(initialData)
返回
?@flkes否,返回一个。检查过载。
public static <T> Stream<T> applyManyFilters(Stream<T> data, Predicate<T>... filters) {
    return data.filter(d -> Arrays.stream(filters).allMatch(f -> f.test(d)));
}