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

流的性能。排序()。限制()

厍和颂
2023-03-14

Java Streams同时使用sortedlimit方法,这两种方法分别返回流的排序版本和仅返回流中指定数量项的流。连续应用这些操作时,例如:

stream.sorted().limit(qty).collect(Collectors.toList())

排序是以排序qty项的方式执行的,还是对整个列表进行排序?换句话说,如果qty是固定的,那么这个操作是否在O(n)中?留档不会单独指定这些方法的性能,也不会相互关联指定这些方法的性能。

我提出这个问题的原因是,这些操作的明显必要实现是排序然后限制,这需要时间Θ(n*log(n))。但是这些操作可以一起在O(n*log(qty))中执行,智能流框架可以在执行之前查看整个流,以优化这种特殊情况。

共有3个答案

有凯泽
2023-03-14

这依赖于实现,也可能取决于流管道是否可以“看穿”排序()和限制()之间的潜在操作。

即使您询问OpenJDK实现,它也可能会发生变化,因为Javadoc对运行时行为没有任何保证。但是没有,目前它没有实现k-min选择算法。

您还必须记住,sorted()不适用于无限流,除非它们已经具有sorted特性。

姚智
2023-03-14

我的StreamEx库中有一个特殊的收集器执行此操作:MoreCollectors。最少(数量)

List<?> result = stream.collect(MoreCollectors.least(qty));

它在内部使用PriorityQueue,在未排序的输入上使用小数量时,实际工作速度明显更快。但是请注意,如果输入大部分是排序的,则sorted()。限制(数量)可能工作得更快,因为TimSort对于预排序数据的速度非常快。

令狐经武
2023-03-14

让我首先概括地指出,Java语言规范对如何实现流没有什么限制。因此,询问Java流的性能并不是很有意义:它在不同的实现之间会有很大的差异。

还要注意,Stream是一个接口。您可以创建自己的类来实现,以便在排序上具有所需的任何性能或特殊行为。因此,即使在一个实现的上下文中,真正询问流的性能也毫无意义。OpenJDK实现有许多类实现接口。

话虽如此,如果我们看一下OpenJDK实现,流的排序结果是SortedOps类(参见这里的源代码),您会发现排序方法最终返回有状态操作的扩展。例如:

private static final class OfInt extends IntPipeline.StatefulOp<Integer>

这些方法检查上游是否已经排序,在这种情况下,它们只是将其传递给下游。对于大小不定的流(即上游流),它们也有特殊的例外情况,这些例外情况预先分配数组,最终进行排序,这将提高效率(相对于它们用于未知大小流的SpinedBuffer)。但是,只要上游尚未排序,它们就会接受所有项目,然后对它们进行排序,然后发送到下游实例的accept方法。

由此得出的结论是,OpenJDK的排序实现收集所有项,然后排序,然后向下游发送。在某些情况下,当下游随后将丢弃一些元素时,这将浪费资源。您可以自由实现自己的专门排序操作,对于特殊情况,这比这更有效。可能最简单的方法是实现一个Collector,它保存流中n个最大或最小项的列表。您的操作可能看起来像:

.collect(new CollectNthLargest(4)).stream()

来代替

.sorted().limit(4)

 类似资料:
  • 哦,那些狡猾的Java8条带有lambdas的溪流。它们非常强大,但是复杂的东西需要一点时间来包裹它。 假设我有一个类型,其属性为。假设我有这些用户的地图 ?

  • 事情是这样的。我在做leetcode 164最大间隙。最佳解决方案是桶排序。 这让我对排序问题有了更多的思考。假设我们有如下列表: 2、5、19、444、-14、89、16、77 我认为,我们可以用两个不同的范围来排列这些数字,(min, mid)(mid, max)和mid-应该是min(max-min)/2; 因此我们得到了(-14215)(216444) 我们将min设置为最左侧,max设置

  • 针对每个接口做限流功能,限流方式有两种: 漏桶策略:每秒处理固定数量的请求,超出请求返回错误信息。可用在秒杀、抢购业务 令牌桶策略:每秒放置固定数量的令牌数,不足的令牌数做等待处理,直到拿到令牌为止。平滑输出,可减轻服务器压力。 两种策略可在后台页面切换 开启限流功能 以springboot为例 application.properties配置redis信息 IndexController中配置:

  • 问题内容: 哦,那些带有lambda的棘手的Java 8流。它们非常强大,但是复杂性要花一点点头才能将其包起来。 假设我有一个带有属性的类型。假设我有一个与名称相关联的用户的地图(例如,登录用户名)。让我们进一步说一下,我有一个比较器的实例来对用户名进行排序(也许使用花哨的排序器等)。 那么,如何获取地图中按用户名排序的用户列表?我可以忽略地图键并执行以下操作: 但是我不得不提取名称才能使用的那一

  • 排序,在编程中经常遇到的算法,我也在几篇文章中介绍了一些关于排序的算法。有的高级语言内置了一些排序函数。本文讲述Python在这方面的工作。供使用python的程序员们参考,也让没有使用python的朋友了解python。领略一番“生命有限,请用Python”的含义。 内置函数sorted()/list.sort()的使用 简单应用 python对list有一个内置函数:sorted(),专门用于

  • 我尝试在和中排序一个大小为100000000的数组,我可以看到它们之间存在巨大的性能差距。对于这个数字,几乎比快倍(在我的机器上)。 我记录了一些结果,发现当大小在10000左右或更小时,swift的速度更快,但一旦数值上升,就会变得比慢得多。 下面是Swift和Kotlin的代码, 迅捷 科特林 下面是两个记录的时间, 迅捷 因此,在这里,您可以看到在大小增加时变得极其缓慢,尽管在数量较小时它会