【发布时间】:2017-04-10 22:26:42
【问题描述】:
我想了解下面给定语句的时间复杂度。(在 Java8 中)
list.stream().collect(groupingBy(...));
有什么想法吗?
【问题讨论】:
标签: java java-8 java-stream time-complexity collectors
我想了解下面给定语句的时间复杂度。(在 Java8 中)
list.stream().collect(groupingBy(...));
有什么想法吗?
【问题讨论】:
标签: java java-8 java-stream time-complexity collectors
这个问题没有通用答案,因为时间复杂度取决于所有操作。由于必须完全处理流,因此基本时间复杂度为O(n),必须乘以每个元素完成的所有操作的成本。这是假设迭代成本本身不比O(n)差,这是大多数流源的情况。
所以,假设没有影响时间复杂度的中间操作,groupingBy 必须评估每个元素的函数,这应该独立于其他元素,因此不会影响时间复杂度(不管它有多昂贵,正如O(…) 时间复杂度只告诉我们,时间如何缩放大量流元素)。然后,它将元素插入到地图中,这可能取决于已包含元素的数量。如果没有自定义的Map 供应商,则地图的类型是未指定的,因此,此处无法声明。
在实践中,可以合理地假设结果将是某种散列映射,默认情况下具有净 O(1) 查找复杂度。所以我们的分组净时间复杂度为O(n)。然后,我们有 下游 收集器。
默认的下游收集器是toList(),它会产生一个未指定的List类型,所以再一次,我们不能说向它添加元素的成本。
当前的实现产生了一个ArrayList,当超过容量时它必须执行复制操作,但是由于容量每次都会增加一个因子,因此仍然存在净复杂度O(n) 用于添加 n 元素。可以合理地假设,未来对 toList() 实施的更改不会使成本比我们今天的成本更糟。所以默认groupingBy集合的时间复杂度很可能是O(n)。
如果我们将自定义Map 收集器与自定义下游收集器一起使用,则复杂性取决于平均组数与每组元素数之比。最坏的情况是地图查找和下游收集器的元素处理(乘以元素数量)中的最坏情况,因为我们可以有一个包含所有项目的组,或者每个项目都在自己的组中。
但通常,您能够预测特定分组操作的偏差,因此您希望计算该特定操作的时间复杂度,而不是依赖于一般情况下关于所有分组操作的陈述。
【讨论】: