如何使用分隔符修改集合的元素

时间:2018-07-26 04:57:10

标签: java-8 spliterator

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

有人可以告诉我有关Spliterator支持的CRUD中的另一种操作。我尝试使用Collection来修改Spliterator中的元素,但是没有用:

    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());

2 个答案:

答案 0 :(得分:2)

Spliterator无法修改基础的Collection,主要是因为Spliterator(与Iterator不同)并不是严格受Collection约束的接口。

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

  

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

     

迭代器允许调用者在迭代过程中使用定义明确的语义从基础集合中删除元素。

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

  

用于遍历和划分源元素的对象。 Spliterator覆盖的元素来源可以是例如数组,Collection,IO通道或生成器函数。


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

为此使用Stream(或IntStream),再加上map()后跟collect()

答案 1 :(得分:1)

这里公认的答案提到的问题是Integer对象是不可变的,因此不能通过其迭代器或拆分器使用集合,因为您不能就地修改整数实例 / em>。但是,如果您认为对象是可变的,则可以通过Iterator#next或在Spliterator#tryAdvance的使用者中获取它们,并将其修改为常规的可变对象(例如,通过公开的setter)。

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

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