如何仅过滤掉Java顺序流中与谓词不匹配的第一个元素?
2022-09-02 21:06:05
我被困在Java流操作的边缘情况...
我想对以下行为进行编码:“从任意一篮子水果中,收集20个最小的,除了最小的梨,因为我们不想要那个。
额外的好处:即将到来的篮子可能根本没有梨。
例子:
- 从[梨5,苹果1,苹果2,苹果10,梨3,梨7],我们想要[苹果1,苹果2,梨5,梨7,苹果10]。
- 从[苹果4,苹果7,梨8,梨2,梨3],我们想要[梨3,苹果4,苹果7,梨8]。
到目前为止,我处于这一步:
output = basket.stream()
.sorted(Comparator.comparing(Fruit::getSize))
//.filter(???)
.limit(20)
.collect(fruitCollector);
这似乎是有状态lambda过滤器的一个案例,我不知道该怎么做。
我不能使用局部布尔值并将其设置为在过滤第一个梨之后,因为lambda中的所有局部变量都必须是最终的。firstPear
true
最坏的情况是,我可以把篮子分成两半,梨和非梨,对梨进行排序,如果有的话,可以适当地将它们子列出。这似乎非常低效和丑陋。有没有更好的方法?
[编辑]答案比较
这里发布的答案有很多变化,其中大多数都是有效的。为了回馈社区,我整理了一个小的测试工具来比较这些算法的性能。
这种比较并不像我想要的那么广泛 - 已经3周了。它仅涵盖简单项目的顺序处理的用法。您可以随意尝试测试工具,并添加更多测试、更多基准测试或您自己的实现。
我的分析:
Algorithm | Author | Perf | Comments -------------------------------------------------------------------------------- Indexed removal | Holger | Best | Best overall, somewhat obscure Stateful predicate | pedromss | Best | Do not use for parallel processing Straightforward approach | Misha | Best | Better when few elements match Custom collector | Eugene | Good | Better when all or no element match Comaprator hack w/ dummy | yegodm | Good | - Comparator hack | xenteros | * | Perf sensitive to output size, fails on edge cases.
我回答了 pedromss 的答案,因为它是我们在项目中实现的,因为它具有良好的性能和“黑匣子”功能(状态管理代码位于外部类中,贡献者可以专注于业务逻辑)。
请注意,接受的答案可能不适合您:查看其他答案,或检查我的测试项目以亲自查看。