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

由于我使用流很多,其中一些处理大量的数据,我认为这是一个好主意,预先分配我的基于收集器的收集器大致的大小,以防止收集增长时的昂贵的重新分配。 所以我想出了这个,其他类型的集合类似:

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()的实现设置了一个Characteristics枚举值Collectors.toCollection()不包含: Characteristics.UNORDEREDCollectors.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没有这种特征,但不依赖于遭遇顺序没有任何问题。

这个特性是否有影响取决于流操作本身和实现细节。 虽然目前的实现可能不会从中获得太多优势,但由于反向传播的困难,这并不意味着未来版本不会。 当然,一个已经无序的流不受Collector UNORDERED特性的影响。 并非所有的流操作都有可能从中受益。

所以更重要的问题是,防止这种潜在的优化(可能在未来)是多么重要。

请注意,还有其他未指定的实现细节,在涉及到第二个变体时会影响潜在的优化。 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);
}

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

链接地址: http://www.djcxy.com/p/91561.html

上一篇: Is it important to use Characteristics.UNORDERED in Collectors when possible?

下一篇: Proper way to pass parameters to query in R DBI