经过大量搜索,我发现Spliterator
支持的唯一操作是从Collection
读取元素。
有人能告诉我CRUD中Spliterator
可以支持的另一个操作吗。我试图使用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
无法修改底层Collection
,主要是因为Spliterator
(与Iterator
不同(不是严格绑定到Collection
的接口。
Iterator
的定义(来自Iterator
的JavaDoc(:
集合上的迭代器。[…]
迭代程序允许调用方在迭代过程中使用定义良好的语义从底层集合中删除元素。
Spliterator
的定义(来自Spliterator
的JavaDoc(:
一个用于遍历和划分源元素的对象。
Spliterator
覆盖的元素源可以是,例如,阵列、Collection
、IO通道或生成器函数。
编辑:我刚刚读了你发布的代码。在这段代码中,您尝试在Spliterator
调用中变异一个不可变的Integer
实例。在这种情况下,Iterator
和Spliterator
都不能工作,因为元素是不可变的。
为此使用Stream
(或IntStream
(,再加上map()
和collect()
。
这里的问题是,正如公认的答案所提到的,Integer
对象是不可变的,因此通过迭代器或分裂器消耗集合都不起作用,因为您不能在适当的位置修改整数实例。但是,如果您的对象被认为是可变的,您可以通过Iterator#next
或在Spliterator#tryAdvance
的使用者中获取它们,并将它们修改为常规可变对象(例如:通过公开的setter(。
作为一个变通解决方案,您可以对集合进行流式处理,将每个整数实例映射到具有所需更改的新整数实例,然后将它们收集回新的TreeSet<Integer>
中。
final Set<Integer> newSet = set.stream()
.map(number -> number + 1)
.collect(Collectors.toCollection(TreeSet::new));