流过滤器的时间复杂度

时间:2017-08-14 22:54:45

标签: java performance java-8 java-stream

我有这样的代码:

List<Listing> Listings = new ArrayList<>();
Listings.add(listing1);
Listings.add(listing2);
...
...
...

Listing listing= listings.stream()
                .filter(l -> l.getVin() == 456)
                .findFirst();

我的问题是过滤过程的时间复杂度是多少?如果它是O(n),我的直觉是将它转换为HashSet,就像数据结构一样,这样时间复杂度就可以变成O(1),是否有一种优雅的方法来实现 with streams ?< / p>

3 个答案:

答案 0 :(得分:7)

O(n)。流过滤在内部使用迭代。

您可以将其转换为地图,如下所示:

Map<Integer, Listing > mapOfVinToListing = listings.stream().collect(Collectors.toMap(Listing::getVin, Functions.identity()); // Assuming vin is unique per listing
mapOfVinToListing.get(456);// O(1)

但是,转换过程也是O(n)。因此,如果您只需要执行一次,请使用过滤器。如果您需要多次查询同一个列表,那么将其转换为地图可能有意义。

您也可以尝试使用并行流。在某些情况下,它们可能更具性能,但这在很大程度上取决于具体情况。

答案 1 :(得分:2)

最糟糕的情况是O(n),但由于Stream是懒惰的,如果之前找到该值,它将停止迭代。如果你需要不断的时间查找,那么转换为Map是一个好主意,代价是额外的空间;如果列表如果巨大,你应该考虑那个方面。事实上,如果列表很小,MapList之间的差异几乎不会引起注意,除非您在时间关键系统中工作。

答案 2 :(得分:1)

filter本身没有终端操作会产生零开销 - 因为它绝对没有;流只由终端操作驱动 - 没有终端操作,没有任何执行。

然后出现filter必须迭代所有元素(可能是所有)(懒惰)的情况。因此,过滤器的时间复杂度将取决于您从中流式传输的来源;在你的情况List中,它将是O(n)

但那将是最坏的情况。就filter 一般而言,我无法预测平均情况,因为它取决于底层来源。