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

由于我使用了很多流,其中一些处理大量数据,我认为最好预先分配基于集合的收集器大小,以防止随着集合的增长而进行昂贵的重新分配。 所以我提出了这个,以及类似的其他集合类型:

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

像这样使用

 Set fooSet = myFooStream.collect(toSetSized(100000)); 

我担心的是Collectors.toSet()的实现设置了一个Collectors.toCollection()没有的Characteristics枚举: Characteristics.UNORDEREDCollectors.toCollection()没有方便的变体来设置超出默认值的所需特性,并且由于可见性问题,我无法复制Collectors.toSet()的实现。 所以,为了设置UNORDERED特性,我不得不这样做:

 static Collector<T,?,Set> 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)精确定义collections家应该如何工作,也可能妨碍收集生成未来版本collections家的内部优化。

因此,在不涉及Collector的其他方面的情况下指定特性的方法将是最佳解决方案,但据我所知,现有API没有提供简单的方法。 但是你自己建立这样的设施很容易:

 public static  Collector characteristics( Collector c, Collector.Characteristics... ch) { Set 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 set=stream .collect(characteristics(toCollection(()->new HashSet<>(capacity)), UNORDERED)); 

或提供您的工厂方法

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

这限制了提供你的特征所需的努力(如果它是一个反复出现的问题),所以提供它们也不会有害,即使你不知道它会产生多大的影响。