当前位置: 首页 > 知识库问答 >
问题:

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

阮炯
2023-03-14

有没有办法使用 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
}

当然,上面的示例无法编译,因为<code>reduce,而不是<code>LongStream。我很好奇上面的代码是否可以写在一行中?

(P.S .先说清楚,这意在成为Java 8如何工作的问题,而不是风格的问题。我同意一行代码的可读性不如循环代码。)

共有3个答案

顾文昌
2023-03-14

要继续回答@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)));
}
顾永福
2023-03-14

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

//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);
}
姜振濂
2023-03-14

我相信这就是你正在寻找的:

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方法来组合一组过滤器。您可以在helper类中使它成为一个很好的实用方法,以便在代码中的任何地方重用,并覆盖其他谓词(< code>BiPredicate 、< code>DoublePredicate 、< code>IntPredicate和< code>Predicate)。

private void applyManyFilters(long[] initialData, LongPredicate... filters) {
    long[] dataToUse = Arrays.stream(initialData)
                             .filter(combine(filters))
                             .toArray();
    // Use filtered data
}
public static LongPredicate combine(LongPredicate... filters) {
    return Arrays.stream(filters)
                 .reduce(LongPredicate::and)
                 .orElse(x -> true);
}
 类似资料:
  • 在空手道中,我希望有一个模式变量,它是响应数据的超集,这样我就可以用相同的模式测试多个请求。 这对于GraphQL应该特别有用,因为请求本身定义了返回的字段。 预期模式: 回答数据: 在本例中,响应返回的所有键。数据应该在架构中,但架构中的任何键都不在响应中。数据应该被忽略。 在空手道中有没有办法做到这一点,或者有没有计划在将来增加这一功能? 编辑:更新了示例,因为唯一遗漏的属性是一个可为空的属性

  • 问题内容: 我的孩子做了一项家庭作业,用Java编写二十一点。我为他提供了一些帮助,但大部分时间他都是自己完成的,实际上效果还不错。他甚至发现了我在计算手值时没有看到的错误。但是,他还没有解决一个难题,我能想到的每个解决方案都非常复杂,而且远远超出了他将能够利用其仍基本的Java技能轻松编写代码的范围。 王牌。实际上,不仅有一个Ace,还有四个Ace,您可能可以一手拿到所有四个Ace。当有一个或多

  • 我正在寻找一个更优雅的方法,将这个指令列表变成一个单一的合并指令,其中键'SKU'作为合并的键。这些列表实际上都是很容易被转化为指令的模型。我没有找到一个更优雅的解决方案使用Pydantic。 Dicts/PydanticInstances列表 所需输出: 当前解决方案:

  • 问题内容: 是否有更可读的方法来检查是否存在嵌入字典的键而无需独立检查每个级别? 可以说我需要在埋藏的对象中获取此值(示例取自Wikidata): 为了确保不会以运行时错误结束,有必要检查每个级别,如下所示: 我可以想到的另一种解决方法是将其包装到一个结构中,对于这样一个简单的任务,我也觉得很尴尬。 我正在寻找类似的东西: 如果所有级别都存在,则返回。 问题答案: 简而言之,使用Python,您必

  • 我使用JPA2.1将PostgreSQL转换为。但是对于不同的JPA提供者,比如EclipseLink和Hibernate,我没有找到一个通用的方法。所以我需要为每个JPA提供者编写不同的转换器。 下面的示例为EclipseLink和Hibernate使用不同的转换器。https://github.com/phstudy/jpa-converter-sample 对于不同的JPA提供者,是否有一种

  • 我正在用Java8为一个文件编写一个解析器。使用读取该文件,并返回一个顺序的。 每一行都映射到一个数据对象,如下所示: 现在我们可以将流中的每一行映射到相应的结果: 但是,流现在包含要删除的值: 如我在中所知,如果需要结果,我如何组合映射/筛选操作?