Java 8 如何修改集合';使用拆分器替换元素

Java 8 如何修改集合';使用拆分器替换元素,java-8,spliterator,Java 8,Spliterator,经过多次搜索,我发现Spliterator支持的唯一操作是从集合中读取元素 有人能告诉我关于CRUD中的另一个操作,该操作可由拆分器支持。我尝试使用拆分器修改集合中的元素,但没有成功: Set<Integer> set = new TreeSet<>(); set.add(2); set.add(3); set.add(5); set.add(6); Spliterator<Integer> si = set.s

经过多次搜索,我发现
Spliterator
支持的唯一操作是从
集合中读取元素

有人能告诉我关于CRUD中的另一个操作,该操作可由
拆分器
支持。我尝试使用
拆分器修改
集合中的元素,但没有成功:

    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());
Set Set=new TreeSet();
增加(2);
增加(3);
增加(5);
增加(6);
Spliterator si=set.Spliterator();
拆分器sa=si.trySplit();
而(sa.tryAdvance(e->e=++e));
System.out.println(“原始迭代器”);
而(si.tryAdvance(e->e=++e));
System.out.println(set.toString());
无法修改底层,主要原因是
拆分器(不像)不是严格的
集合
绑定接口

迭代器的定义(来自):

集合上的迭代器。[……]

迭代器允许调用方在迭代期间使用定义良好的语义从基础集合中删除元素

拆分器的定义(来自):

用于遍历和划分源元素的对象。
拆分器
所涵盖的元素源可以是,例如,阵列、输入/输出通道或生成器函数


编辑:我刚刚读了你发布的代码。在这段代码中,您尝试在
拆分器
调用中变异一个不可变的
整数
实例。在这种情况下,
Iterator
Spliterator
都不能工作,因为元素是不可变的


使用a(或an)和后跟。

此处的问题(如接受的答案所述)是
Integer
对象是不可变的,因此通过迭代器或拆分器使用集合都不起作用,因为您无法在适当的位置修改Integer实例。但是,如果您的对象被认为是可变的,您可以通过
迭代器#next
或在
拆分器#tryAdvance
的使用者中获取它们,并将它们作为常规可变对象进行修改(例如:通过公开的setter)

作为一种变通解决方案,您可以对集合进行流式处理,将每个整数实例映射到具有所需更改的新整数实例,从那里您可以将它们收集回新的
TreeSet

final Set newSet=Set.stream()
.map(编号->编号+1)
.collect(收集器.toCollection(TreeSet::new));

我不同意迭代器严格绑定到集合对象的概念,因为下面的代码语句也是有效的,可以从无限源流中获取等效的迭代器。因此,语义定义良好的移除概念并不成立
final Iterator number=Stream.iterate(1,n->n+1.Iterator()嗯,我可能用了“严格”和
Collection
这两个词来夸大。不是“严格”的,因为正如您所示,我们在许多其他地方遇到了
Iterator
s(例如,在Java8之前,包括我在内的人经常编写自定义
Iterator
实现)。另一方面,
迭代器
被定义为在
集合
上进行迭代(这就是为什么它有一个方法——尽管它是可选的)<另一方面,code>Spliterator
,明确指出它不一定是
集合
绑定的。这种解释是误导性的,因为即使直接在集合上调用
forEach
,也不会改变这样一个事实,即像
e->e=++e
这样的消费者甚至会执行两个过时的操作而没有效果
++e
修改参数
e
,赋值
e=
再次修改参数,以将由于
++e
操作而已经具有的值赋值给它。因此,无论我们使用的是
int
还是
Integer
,参数变量都是可变的,但与方法一样,修改参数对调用者没有影响,不管我们使用的是哪个接口。@Holger:我一读代码就编辑了答案,注意到了它的作用。我不确定我是否应该在当前答案的基础上做更多的事情。对答案进行预处理可以吗?
final Set<Integer> newSet = set.stream()
    .map(number -> number + 1)
    .collect(Collectors.toCollection(TreeSet::new));