如何修改集合's元素



经过大量搜索,我发现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实例。在这种情况下,IteratorSpliterator都不能工作,因为元素是不可变的。

为此使用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));

最新更新