首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SortedSet::removeAll( headSet )失败,但从headSet派生另一个集合成功。为什么?

SortedSet::removeAll( headSet )失败,但从headSet派生另一个集合成功。为什么?
EN

Stack Overflow用户
提问于 2015-07-13 04:50:18
回答 1查看 342关注 0票数 3

来自Java8中的TreeSet ( SortedSet):

  1. 我调用::headSet方法来获取排序集合前面的对象的SortedSet
  2. 我调用::removeAll来删除最前端的对象。 BAM抛出一个ConcurrentModificationException

但是,如果我从SortedSet中再做一个headSet,并将派生的设置传递给::removeAll,就没有问题了。

为什么?

使用Java 8更新45的演示代码。启用行//sortedSet.removeAll( headSet );以查看抛出的异常。

代码语言:javascript
复制
String cockatiel = "Cockatiel";

SortedSet sortedSet = new TreeSet< String >( );
sortedSet.add( "Dog" );
sortedSet.add( "Cat" );
sortedSet.add( "Bird" );
sortedSet.add( "Elephant" );
sortedSet.add( cockatiel );  // Passing var rather than literal.
sortedSet.add( "Guppy" );

System.out.println( "Before: " + sortedSet );

// Direct way. FAIL
SortedSet< String > headSet = sortedSet.headSet( cockatiel );
System.out.println( "headSet: " + headSet );
//sortedSet.removeAll( headSet );  // Fails. Throws java.util.ConcurrentModificationException.

// Derived way. PASS
SortedSet<String> headSetDerived = new TreeSet<String>( headSet); // Make a TreeSet from a TreeSet.
sortedSet.removeAll( headSetDerived );  // Succeeds. Why?

System.out.println( "After: " + sortedSet );
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-07-13 05:12:53

原始集支持的headSet

在第一个方法中,您在修改集合(通过删除元素)的同时,对其进行迭代(以获得要删除的元素)。这就抛出了异常。请记住,头集是由原始集支持的,所以修改原始集最终会修改头集--这是在对头集进行迭代时做不到的。

摘自TreeSet::headSet文档(粗体强调为我的):

返回此集合…的一部分的视图返回集由此集支持,因此返回集中的更改反映在该集合中,反之亦然。

解决办法

通常有两种方法可以避免这种情况。一种是直接使用迭代器并使用它的remove()方法。另一种方法是将迭代和修改分开,首先迭代创建集合的副本,然后迭代副本以从原始副本中删除;这是您在第二种方法中所做的。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31375581

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档