簡體   English   中英

收集器的運行時復雜度#toList

[英]Runtime complexity of Collectors#toList

在 Java 庫源代碼中, Collectors#toList方法是這樣定義的:

public static <T>
Collector<T, ?, List<T>> toList() {
    return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
                               (left, right) -> { left.addAll(right); return left; },
                               CH_ID);
}

我們將BinaryOperator視為CollectorImpl構造函數的第三個參數,它在線性時間內合並兩個子結果。

這是否意味着,在通過Stream#collect方法頻繁使用此函數的情況下,我們可以獲得平方計算時間?

考慮這個代碼:

List<Integer> desc = Stream.iterate(n, k -> k - 1).limit(n + 1)
    .collect(Collectors.toList());

desc.parallelStream()
    .map(k -> {
        try {
            Thread.sleep(k * 500);
        } catch (InterruptedException ignored) {
        }
        return k;
    })
    .collect(Collectors.toList());

第二個流的元素碰巧是按降序計算的。 collect 方法可以做的最簡單的事情是將每個數字包裝成List並將所有下一個數字添加到它,總共有平方復雜度,多么悲傷。

在這種情況下,輸入desc列表將根據系統具有的硬件線程數分為幾個獨立的部分。 通常它是 4 核系統上的 16 個部分(雖然它沒有指定並且可能會改變)。 每個部分將使用累加器獨立處理,然后使用組合器將結果合並在一起。 所以它不會下降到二次復雜度,但是是的,會進行許多不必要的復制。

實際上使用toArray()方法效率更高。 它檢查流源特征,在您的情況下,它特別優化,因為源是 SIZED 和 SUBSIZED,因此可以將結果寫入單個數組而無需任何額外的復制。 如果你需要List ,你可以考慮使用Arrays.asList(desc.parallelStream()....toArray(Integer[]::new))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM