如何使用拆分器修改集合的元素

How to modify collection's elements with a spliterator

经过大量搜索,我发现 Spliterator 唯一支持的操作是从 Collection 读取元素。

谁能告诉我 Spliterator 支持的 CRUD 中的另一个操作。我尝试使用 Spliterator 修改 Collection 中的元素,但没有成功:

    Set<Integer> set = new TreeSet<>();
    set.add(2);
    set.add(3);
    set.add(5);
    set.add(6);
    Spliterator<Integer> si = set.spliterator();
    Spliterator<Integer> sa  = si.trySplit();
    while(sa.tryAdvance(e ->  e= ++e));

    System.out.println("original iterator");
    while(si.tryAdvance(e-> e = ++e));
    System.out.println(set.toString());

Spliterator cannot modify an underlying Collection, mainly because Spliterator (unlike Iterator) 不是严格的 Collection 绑定接口。

Iterator的定义(来自Iterator's JavaDoc):

An iterator over a collection. [...]

Iterators allow the caller to remove elements from the underlying collection during the iteration with well-defined semantics.

Spliterator的定义(来自Spliterator's JavaDoc):

An object for traversing and partitioning elements of a source. The source of elements covered by a Spliterator could be, for example, an array, a Collection, an IO channel, or a generator function.


编辑:我刚刚阅读了您发布的代码。在此代码中,您尝试在 Spliterator 调用中改变不可变的 Integer 实例。在这种情况下,IteratorSpliterator 都不起作用,因为元素是不可变的。

使用 Stream (or an IntStream) for this, together with a map() followed by collect().

已接受的答案提到的问题是 Integer 对象是不可变的,因此通过其迭代器或拆分器使用您的集合都不起作用,因为您无法修改整数实例 就地。但是,如果您的对象被认为是可变的,您可以通过 Iterator#next 或在 Spliterator#tryAdvance 的使用者中获取它们并将它们修改为常规可变对象(例如:通过暴露的 setter)。

作为解决方案,您可以流式传输您的集合,将每个整数实例映射到具有所需更改的新整数实例,从那里您可以将它们收集回新的 TreeSet<Integer>

final Set<Integer> newSet = set.stream()
    .map(number -> number + 1)
    .collect(Collectors.toCollection(TreeSet::new));