在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)
的想法添加到,但作为可重用的帮助器方法。将您的答案中使用可重用的帮助器方法的想法添加到,但该方法返回组合谓词,因此它的使用更像流。参见whenlong[]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)));
}