优先考虑Java中的流过滤器函数
我正在寻找一个选项来过滤插入流但使用优先级。优先考虑Java中的流过滤器函数
以下为伪代码:
results.stream().filter(prio1).ifNotFound(filter(prio2)).collect(toList())
结果的列表,由第一标准被过滤称为“prio1
”,如果不存在没有找到匹配第二滤波器应适用于尝试滤波器在第二个标准被称为prio2
,然后结果将被收集
如何在Java 8中使用流实现此?
我正在寻找流中的一行。
您需要stream()
你的结果的两倍,但下面应该工作作为一个班轮:
results.stream().filter(results.stream().anyMatch(prio1) ? prio1 : prio2).collect(Collectors.toList());
(感谢flakes的第一个发布使用类似的策略多衬垫。 )
编辑:由于一些优秀的新的答案已经水落石出,我以为我会提供这种多数据流的短期防御/ anyMatch
战略出不来克参考此主题的某些其他部分:
As pointed out by eckes,
anyMatch
被优化以返回早,因此最小的时间花费在阅读了额外流(尤其是对于其中prio1
是可能匹配的情况下)。实际上,anyMatch
只会读取后备(prio2
)情况下的整个数据流,因此对于平均运行,您只能遍历一个和一个分数列表长度。使用
Collectors.groupingBy(...)
方法在每种情况下构造一个Map和两个List,而上面的方法只能创建至多一个List。随着results
的大小增加,这里的内存开销的差异将变得非常重要。对整个流进行分组,因此即使第一个元素碰巧通过prio1
,每个元素都必须再次针对prio1.or(prio2)
和针对prio1
进行检查。groupingBy
没有考虑prio1
和prio2
不互相排斥的情况。如果prio2.test(e)
可以返回true
对于通过prio1
的某些e
,这些元素将在回退prio2
列表中丢失。一次使用anyMatch
和一个过滤器可以避免此问题。上述方法的行长度和复杂度对我来说似乎更容易管理。
只是做一个条件:
final List<Foo> foo;
if (results.stream().anyMatch(prio1)) {
foo = results.stream().filter(prio1).collect(Collectors.toList());
} else {
foo = results.stream().filter(prio2).collect(Collectors.toList());
}
如果你真的想要一个衬垫,那么你可以做到以下几点,但有没有办法让周围流列表中的两倍。我会争辩说,if/else
版本更清洁,更容易维护。
final List<Foo> foo = results.stream()
.filter(results.stream().anyMatch(prio1)? prio1 : prio2)
.collect(Collectors.toList());
只是另一种方法是不使用anyMatch
,但对结果操作之前,而组中的条目。
Optional.of(results.stream()
.filter(prio1.or(prio2))
.collect(Collectors.groupingBy(prio1::test)))
.map(map -> map.getOrDefault(true, map.get(false)))
.ifPresent(System.out::println);
我以前Optional
,让你有一个“一个班轮”(刚刚格式化它,这样它会更易读)。您也可以使用orElseGet(Collections::emptyList)
而不是ifPresent
并将结果保存到List<String>
。
的groupingBy
把从prio1
和prio2
过滤条目,将全部prio1
-matching项进入关键true
,其余prio2
-matching项为false
。如果我们在true
中没有任何条目,那么将默认返回prio2
已过滤的条目。如果没有任何prio1
或prio2
匹配结果,则不会发生任何情况。
请注意,如果您直接返回Map
,那么只有prio2
匹配条目在false
中匹配(如果您的筛选器是互斥的)。
哦,这很酷!巧妙使用'groupingBy'。感谢教我新东西:) – gyre
非常好,比我的黑客好得多。太糟糕了,你不能使用'partitioningBy()'。 'map()'函数虽然有点不必要的聪明。 '.map(map - > map.getOrDefault(true,map.get(false)))'在功能和性能上是等价的,只是稍微长一点,而且更易读,IMO。 – shmosel
@shmosel你也可以使用'partitioningBy',但是你需要检查列表中是否有空,而现在我们只需检查'null'。你是对的......'getOrDefault'在这里更具可读性...会改变...... – Roland
目前还不清楚你的意思是'ifNotFound'。 –
你可以说第二个过滤器prio2不会被应用在哪种情况下? – MigSena
所有项目应与prio1首先匹配,如果找不到,则再次将所有项目匹配到prio2 – Ckkn