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

时间:2018-10-12 15:24:33

标签: java java-8 functional-programming java-stream predicate

我被困在为进行函数式编程而做的一项练习中,所以我的主要问题是如何对集合元素的传递谓词进行计数,以及是否符合给定的阈值而不是将其收集到集合中。最后的收藏。

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

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

1 个答案:

答案 0 :(得分:2)

我首先创建一个通用实用程序方法,该方法检查给定元素是否与谓词中的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,我就会使流短路。这是为了避免继续评估其他谓词。

现在只需收集上述方法返回true的所有字符串:

List<String> result = stringList.stream()
    .filter(s -> matchingSome(s, predicateList, threshold))
    .collect(Collectors.toList());