我有这样的代码:
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>
答案 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
是一个好主意,代价是额外的空间;如果列表如果巨大,你应该考虑那个方面。事实上,如果列表很小,Map
和List
之间的差异几乎不会引起注意,除非您在时间关键系统中工作。
答案 2 :(得分:1)
filter
本身没有终端操作会产生零开销 - 因为它绝对没有;流只由终端操作驱动 - 没有终端操作,没有任何执行。
然后出现filter
必须迭代所有元素(可能是所有)的(懒惰)的情况。因此,过滤器的时间复杂度将取决于您从中流式传输的来源;在你的情况List
中,它将是O(n)
。
但那将是最坏的情况。就filter
一般而言,我无法预测平均情况,因为它取决于底层来源。