簡體   English   中英

盡可能在收集器中使用Characteristics.UNORDERED很重要嗎?

[英]Is it important to use Characteristics.UNORDERED in Collectors when possible?

由於我使用了很多流,其中一些處理大量數據,我認為預先分配基於集合的收集器大小是一個好主意,以防止隨着集合的增長而進行昂貴的重新分配。 所以我想出了這個,以及類似的其他集合類型:

public static <T> Collector<T, ?, Set<T>> toSetSized(int initialCapacity) {
    return Collectors.toCollection(()-> new HashSet<>(initialCapacity));
}

像這樣使用

Set<Foo> fooSet = myFooStream.collect(toSetSized(100000));

我擔心的是Collectors.toSet()的實現設置了一個Collectors.toCollection()沒有的Characteristics枚舉: Characteristics.UNORDERED Collectors.toCollection()沒有方便的變體來設置超出默認值的所需特性,並且由於可見性問題,我無法復制Collectors.toSet()的實現。 因此,為了設置UNORDERED特性,我不得不這樣做:

static<T> Collector<T,?,Set<T>> toSetSized(int initialCapacity){
    return Collector.of(
            () -> new HashSet<>(initialCapacity),
            Set::add,
            (c1, c2) -> {
                c1.addAll(c2);
                return c1;
            },
            new Collector.Characteristics[]{IDENTITY_FINISH, UNORDERED});
}

所以這里是我的問題:1。這是我唯一的選擇,為自定義toSet() 2之類的東西創建一個無序收集器。如果我希望它理想地工作,是否有必要應用無序特征? 在這個論壇上讀到了一個問題,在那里我了解到無序特征不再向后傳播到Stream中。 它仍然有用嗎?

首先, CollectorUNORDERED特征是幫助表演而不是其他任何東西。 Collector沒有這個特征但不依賴於遭遇順序沒有錯。

此特性是否具有影響取決於流操作本身和實現細節 雖然目前的實現可能不會從中消耗很多優勢,但由於反向傳播的困難,它並不意味着未來的版本不會。 當然,已經無序的流不受CollectorUNORDERED特性的影響。 並非所有流操作都有可能從中受益。

因此,更重要的問題是不要阻止這種潛在的優化(可能在將來)是多么重要。

請注意,還有其他未指定的實現細節,影響了第二個變體的潛在優化。 toCollection(Supplier)收集器具有未指定的內部工作方式,僅保證提供Supplier生產的類型的最終結果。 相比之下, Collector.of(() -> new HashSet<>(initialCapacity), Set::add, (c1, c2) -> { c1.addAll(c2); return c1; }, IDENTITY_FINISH, UNORDERED)精確定義收藏家應該如何工作,也可能妨礙收集產生未來版本收藏家的內部優化。

因此,在不涉及Collector的其他方面的情況下指定特性的方法將是最佳解決方案,但據我所知,現有API沒有提供簡單的方法。 但是你自己建立這樣的設施很容易:

public static <T,A,R> Collector<T,A,R> characteristics(
                      Collector<T,A,R> c, Collector.Characteristics... ch) {
    Set<Collector.Characteristics> o = c.characteristics();
    if(!o.isEmpty()) {
        o=EnumSet.copyOf(o);
        Collections.addAll(o, ch);
        ch=o.toArray(ch);
    }
    return Collector.of(c.supplier(), c.accumulator(), c.combiner(), c.finisher(), ch);
}

用這種方法,很容易說,例如

HashSet<String> set=stream
    .collect(characteristics(toCollection(()->new HashSet<>(capacity)), UNORDERED));

或提供您的工廠方法

public static <T> Collector<T, ?, Set<T>> toSetSized(int initialCapacity) {
    return characteristics(toCollection(()-> new HashSet<>(initialCapacity)), UNORDERED);
}

這限制了提供你的特征所需的努力(如果它是一個反復出現的問題),所以即使你不知道它會產生多大的影響,提供它們也不會有什么壞處。

暫無
暫無

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

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