由于我大量使用流,其中一些处理大量数据,所以我认为预先分配具有大致大小的基于收藏的收集器是个好主意,以防止随着收集量的增加而进行昂贵的重新分配。所以我想出了这个,和其他收集类型类似的:
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这样简单的东西创建无序收集器的唯一选择吗?如果我想让它在理想情况下工作,是否有必要应用无序特性?我读过a question on this forum,其中我了解到无序特性不再被反向传播到流中。它还能起作用吗?
发布于 2016-05-09 12:47:58
首先,UNORDERED的Collector特性是为了帮助性能,而不是其他任何东西。Collector没有这个特性,但不依赖于遇到顺序,这没有什么问题。
这个特性是否有影响取决于流操作本身和实现细节。虽然由于反向传播的困难,当前的实现可能没有太多的优势,但这并不意味着未来的版本不会,当然,已经无序的流不受Collector的Collector特性的影响。并不是所有的流操作都有可能从中受益。
因此,更重要的问题是,不阻止这种潜在的优化(也许在将来)有多重要。
请注意,还有其他未指定的实现细节,当涉及到第二个变体时,会影响潜在的优化。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);
}这限制了提供特性所需的努力(如果这是一个反复出现的问题),所以提供它们不会有什么影响,即使您不知道它会产生多大的影响。
https://stackoverflow.com/questions/37063512
复制相似问题