使用谓词集合过滤集合并符合阈值

Filtering collection with collection of predicates and conforming to threshold

我被困在我正在做的一项练习中,以便稍微了解一下函数式编程,所以我的主要问题是如何计算集合元素上传递的谓词,以及它是否符合给定的阈值而不是 collect到最终合集。

我知道如何做到无门槛,这是我的解决方案:

List<String> filter(List<Predicate<String>> predicateList, List<String> stringList) {
    return stringList.stream()
                     .filter(predicateList.stream()
                                          .reduce(x -> !(x.isEmpty()), Predicate::and))
                     .collect(Collectors.toList());
}

但是当有参数确定需要传递多少百分比的谓词才能收集字符串时我该怎么办,假设方法的主体可能如下所示:

List<String> filtrr(List<Predicate<String>> predicateList, List<String> stringList, Double threshold) {}

编辑: 例如方法应该像这样通过单元测试:

@Test
void filtrrTest() {
    Double threshold = 0.65;

    Predicate<String> predicate = p -> p.contains("lorem");
    Predicate<String> predicate1 = p -> p.length() > 10;
    Predicate<String> predicate2 = p -> p.contains("sed");

    List<Predicate<String>> predicateList = Arrays.asList(predicate, predicate1, predicate2);

    String string = "lorem ipsum dolor sit amet sed";
    String string1 = "consectetur adipiscing elit, sed do eiusmod";
    String string2 = "ipsum";
    String string3 = "adipiscing elit";
    String string4 = "sed do eiusmod";

    List<String> stringList = Arrays.asList(string, string1, string2, string3, string4);
    List<String> expectedList = Arrays.asList(string, string1, string4);

    assertEquals(expectedList, ClassName.filtrr(predicateList, stringList, threshold));
}

我会首先创建一个通用实用方法来检查给定元素是否与谓词的 threshold % 匹配:

public static <T> boolean matchingSome(
        T elem, 
        List<Predicate<T>> predicates, 
        double threshold) {

    long predsToMatch = (long) ((double) predicates.size() * threshold);

    long predsMatched = predicates.stream()
        .filter(p -> p.test(elem))
        .limit(predsToMatch) // this limit is to short-circuit as soon as
        .count();            // predsToMatch predicates evaluate to true

    return predsMatched == predsToMatch;
}

请注意,一旦 predsToMatch 谓词的计算结果为 true,我就会将流短路。这是为了避免继续评估进一步的谓词。

现在只需收集上述方法 returns true:

的所有字符串
List<String> result = stringList.stream()
    .filter(s -> matchingSome(s, predicateList, threshold))
    .collect(Collectors.toList());