[英]Filtering a stream when given multiple conditions in parameters
我正在尝试创建一个 function ,它采用多个谓词条件并根据这些条件过滤 stream 。 我找不到任何东西,但我的 retList 似乎只包含输入而不是输入的过滤版本。
以下是我得到的指示:
//TODO Make a Stream of Integer and set it equal to input for each predicate p on conditions, set this stream variable equals to the result of applying filter(p) to the stream. 完成每个循环后,将生成的 stream 收集到一个列表中,就像我们在之前的问题中所做的那样,返回结果列表
这是我目前拥有的:
public static List<Integer> matchAll(Stream<Integer> input, Predicate<Integer>... conditions) {
Stream<Integer> stream = input;
Stream.of(conditions).peek(p -> stream.filter(p));
List<Integer> retList = stream.collect(Collectors.toList());
return retList;
}
这就是它的测试方式:
public static void main(String[] args) {
Stream<Integer> stream = Stream.of(5,7,9,11,13,14,21,28,35,42,49,56,63,70,71);
Predicate<Integer> p0 = n -> n > 10;
Predicate<Integer> p1 = n -> n % 2 != 0;
Predicate<Integer> p2 = n -> isPrime(n);
System.out.println(Matcher.matchAll(stream, p0, p1, p2));
// should get [11, 13, 71]
}
但我实际得到的是输入 [5,7,9,11,13,14,21,28,35,42,49,56,63,70,71]。
尝试
public static List<Integer> matchAll(List<Integer> input, Predicate<Integer>... conditions) {
Stream<Integer> streams = input.stream();
for (Predicate<Integer> predicate : conditions) {
streams = streams.filter(predicate);
}
return streams.collect(Collectors.toList());
}
public static void main(String[] args) {
List<Integer> list = Arrays.asList(5, 7, 9, 11, 13, 14, 21, 28, 35, 42, 49, 56, 63, 70, 71);
Predicate<Integer> p0 = n -> n > 10;
Predicate<Integer> p1 = n -> n % 2 != 0;
Predicate<Integer> p2 = n -> isPrime(n);
System.out.println(matchAll(list, p0, p1, p2)); // [11, 13, 71]
}
您可以简单地在matchAll
方法中创建一个复合Predicate
并使用它来过滤输入 stream 为:
public static List<Integer> matchAll(Stream<Integer> input, Predicate<Integer>... conditions) {
Predicate<Integer> compositePredicate =
Arrays.stream(conditions).reduce(Predicate::and).orElse(p -> true); // or else filter in all
return input.filter(compositePredicate).collect(Collectors.toList());
}
正如Holger 所建议的,您也可以使用:
return Arrays.stream(conditions)
.reduce(Predicate::and)
.map(input::filter) // Optional.map here
.orElse(input)
.collect(Collectors.toList()); // terminal operation
在您当前的实现中,您不会将过滤的“结果”存储在任何地方。 filter
方法不会修改原来的 stream,它是不可变的,而是返回一个新的 stream,它只包含来自原始 stream 的匹配值。
实现此目的的一种方法是遍历您的条件,将以前的 stream 替换为包含应用过滤的新条件:
public static List<Integer> matchAll(Stream<Integer> input, Predicate<Integer>... conditions) {
Stream<Integer> stream = input;
for (Predicate<Integer> condition : conditions) {
stream = stream.filter(condition);
}
return stream.collect(Collectors.toList());
}
在您的 matchAll function 中,您可以考虑将以下 2 行更改为 1 行。 检查它是否适用于数据输入 stream 的多个谓词过滤器。
从改变
Stream.of(conditions).peek(p -> stream.filter(p));
List<Integer> retList = stream.collect(Collectors.toList());
改成
List<Integer> retList = stream.filter(t -> Arrays.stream(conditions).allMatch(f -> f.test(t))).collect(Collectors.toList());
我认为它应该给出预期的 output。 希望能帮助到你!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.