来自Java8中的TreeSet ( SortedSet):
::headSet方法来获取排序集合前面的对象的SortedSet。::removeAll来删除最前端的对象。
BAM抛出一个ConcurrentModificationException。但是,如果我从SortedSet中再做一个headSet,并将派生的设置传递给::removeAll,就没有问题了。
为什么?
使用Java 8更新45的演示代码。启用行//sortedSet.removeAll( headSet );以查看抛出的异常。
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 );发布于 2015-07-13 05:12:53
原始集支持的headSet
在第一个方法中,您在修改集合(通过删除元素)的同时,对其进行迭代(以获得要删除的元素)。这就抛出了异常。请记住,头集是由原始集支持的,所以修改原始集最终会修改头集--这是在对头集进行迭代时做不到的。
摘自TreeSet::headSet文档(粗体强调为我的):
返回此集合…的一部分的视图。返回集由此集支持,因此返回集中的更改反映在该集合中,反之亦然。
解决办法
通常有两种方法可以避免这种情况。一种是直接使用迭代器并使用它的remove()方法。另一种方法是将迭代和修改分开,首先迭代创建集合的副本,然后迭代副本以从原始副本中删除;这是您在第二种方法中所做的。
https://stackoverflow.com/questions/31375581
复制相似问题