当前位置: 首页 > 知识库问答 >
问题:

如何只过滤掉Java序列流中不匹配谓词的第一个元素?

丌官博文
2023-03-14

我陷入了java流操作的边缘案例...

我想对以下行为进行编码:“从一个任意的水果篮子中,收集20个最小的,除了最小的梨,因为我们不想那样。”

额外的奖励:来的篮子可能没有任何梨。

    null
output = basket.stream()
    .sorted(Comparator.comparing(Fruit::getSize))
    //.filter(???)
    .limit(20)
    .collect(fruitCollector);

我不能使用本地firstpear布尔值并在筛选第一个pear后将其设置为true,因为lambda中的所有局部变量都必须是final的。

最坏的情况是,我可以将篮子一分为二,梨和非梨,对梨进行排序,如果有的话,适当地将它们子列表。这看起来很低效,也很难看。有更好的办法吗?

这里贴出的答案多种多样,大多数都是有效的。为了回馈社区,我拼凑了一个小测试套件来对比这些算法的性能。

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.

请注意,被接受的答案可能不是对您最好的:回顾其他的,或者检查我的测试项目,亲自看看。

共有1个答案

冀越
2023-03-14

可以使用有状态谓词:

class StatefulPredicate<T> implements Predicate<T> {

    private boolean alreadyFiltered;
    private Predicate<T> pred;

    public StatefulPredicate(Predicate<T> pred) {
        this.pred = pred;
        this.alreadyFiltered = false;
    }

    @Override
    public boolean test(T t) {
        if(alreadyFiltered) {
            return true;
        }

        boolean result = pred.test(t);
        alreadyFiltered = !result;
        return result;
    }
}

    Stream.of(1, -1, 3, -4, -5, 6)
        .filter(new StatefulPredicate<>(i -> i > 0))
        .forEach(System.out::println);

打印:1,3,-4,-5,6

如果并发性是一个问题,则可以使用原子布尔值。

 类似资料:
  • 问题内容: 我想要一种惯用的方式来找到与谓词匹配的列表中的第一个元素。 当前代码非常丑陋: 我已经考虑过将其更改为: 但是必须有一些更优雅的方法……如果返回一个值而不是没有找到匹配项引发异常,那将是一个很好的选择。 我知道我可以像这样定义一个函数: 但是,如果已经有内置的插件开始用这样的实用函数填充代码,这是很鸡肋的(人们可能不会注意到它们已经在那里,因此随着时间的推移它们会不断重复出现)。 问题

  • 我收集了< code > 我想找到“每种类型中的一种”,尽管我想找到产品集合中每个谓词的第一个匹配项。 目前我的代码如下: 但这当然会多次迭代产品集合,这是不需要的,因为在我的例子中,我有100000个产品和64个谓词,并且需要很长时间。 在我的特例中,谓词是互斥的:如果一个谓词返回true,那么对于该特定产品,所有其他谓词都可以跳过。因为我使用了< code>findFirst,所以对于所有其他

  • 要求是使用流使用多个匹配条件从Map列表中获取所有匹配和非匹配记录。即不是只有一个过滤器来比较“Email”,而是需要用多个过滤器谓词来比较Email和Id来比较两个匹配记录的列表。 清单1: 清单2: 使用流,我能够找到匹配和不匹配的记录,使用电子邮件的单个筛选谓词:匹配记录: 不匹配记录: 有没有一种方法可以同时比较电子邮件和Id比较,而不仅仅是电子邮件

  • 我有一个接口,它提供了一个方法,返回一个,其中包含一个

  • 问题内容: 我想做类似的事情: Python的标准库中是否有类似行为? 我知道在这里自己动手很容易,但是我正在寻找一种更标准的方法。 问题答案: 您可以使用filter方法: 或列表理解: 要查找单个元素,可以尝试: 尽管如果没有匹配项将引发异常,因此您可能希望将其包装在try / catch中。方括号()使之成为生成器表达式,而不是列表理解。 就我个人而言,尽管我只是使用常规的过滤器/理解并采用

  • 我有一个包含有4个参数(x,y,iD和myType)的对象的ArrayList。我想验证这个ArrayList中是否有具有特定坐标的对象,独立于它们的iD和myType参数。我想使用但当对象只有一个参数时。 以下是全部代码: 例如,如果我想验证是否有一个具有坐标(3.5,4.5)的对象,我应该如何继续?有没有简单的方法? 谢谢你的帮忙