Ern*_*dis 333 java iterator list arraylist
我试图删除一些元素ArrayList迭代它像这样:
for (String str : myArrayList) {
if (someCondition) {
myArrayList.remove(str);
}
}
Run Code Online (Sandbox Code Playgroud)
当然,我ConcurrentModificationException试图在迭代时同时从列表中删除项目时得到一个myArrayList.有没有一些简单的解决方案来解决这个问题?
ars*_*jii 545
Iterator<String> iter = myArrayList.iterator();
while (iter.hasNext()) {
String str = iter.next();
if (someCondition)
iter.remove();
}
Run Code Online (Sandbox Code Playgroud)
Kev*_*lia 178
作为其他人的答案的替代方案,我总是这样做:
List<String> toRemove = new ArrayList<String>();
for (String str : myArrayList) {
if (someCondition) {
toRemove.add(str);
}
}
myArrayList.removeAll(toRemove);
Run Code Online (Sandbox Code Playgroud)
这将避免您必须直接处理迭代器,但需要另一个列表.无论出于何种原因,我总是喜欢这条路线.
Mik*_*sky 87
Java 8用户可以这样做: list.removeIf(...)
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
list.removeIf(e -> (someCondition));
Run Code Online (Sandbox Code Playgroud)
它将删除列表中的元素,满足someCondition
Eri*_*ein 61
你必须使用迭代器的remove()方法,这意味着没有增强的for循环:
for (final Iterator iterator = myArrayList.iterator(); iterator.hasNext(); ) {
iterator.next();
if (someCondition) {
iterator.remove();
}
}
Run Code Online (Sandbox Code Playgroud)
Dim*_*huk 35
不不不!
在单线程任务中,您不需要使用Iterator,而且还需要使用CopyOnWriteArrayList(由于性能损失).
解决方案更简单:尝试使用规范for循环而不是for-each循环.
根据Java版权所有者(几年前Sun,现在是Oracle)for-each循环指南,它使用迭代器来遍历集合并隐藏它以使代码看起来更好.但是,不幸的是,正如我们所看到的,它产生的问题多于利润,否则这个话题就不会出现.
例如,当在修改后的ArrayList上进入下一次迭代时,此代码将导致java.util.ConcurrentModificationException:
// process collection
for (SomeClass currElement: testList) {
SomeClass founDuplicate = findDuplicates(currElement);
if (founDuplicate != null) {
uniqueTestList.add(founDuplicate);
testList.remove(testList.indexOf(currElement));
}
}
Run Code Online (Sandbox Code Playgroud)
但是下面的代码工作得很好:
// process collection
for (int i = 0; i < testList.size(); i++) {
SomeClass currElement = testList.get(i);
SomeClass founDuplicate = findDuplicates(currElement);
if (founDuplicate != null) {
uniqueTestList.add(founDuplicate);
testList.remove(testList.indexOf(currElement));
i--; //to avoid skipping of shifted element
}
}
Run Code Online (Sandbox Code Playgroud)
因此,尝试使用索引方法迭代集合并避免for-each循环,因为它们不等同!For-each循环使用一些内部迭代器,它检查集合修改并抛出ConcurrentModificationException异常.要确认这一点,请在使用我发布的第一个示例时仔细查看打印的堆栈跟踪:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at TestFail.main(TestFail.java:43)
Run Code Online (Sandbox Code Playgroud)
对于多线程使用相应的多任务方法(如synchronized关键字).
虽然其他建议的解决方案有效,但如果您确实希望解决方案成为线程安全的,那么您应该使用CopyOnWriteArrayList替换ArrayList
//List<String> s = new ArrayList<>(); //Will throw exception
List<String> s = new CopyOnWriteArrayList<>();
s.add("B");
Iterator<String> it = s.iterator();
s.add("A");
//Below removes only "B" from List
while (it.hasNext()) {
s.remove(it.next());
}
System.out.println(s);
Run Code Online (Sandbox Code Playgroud)
List myArrayList = Collections.synchronizedList(new ArrayList());
//add your elements
myArrayList.add();
myArrayList.add();
myArrayList.add();
synchronized(myArrayList) {
Iterator i = myArrayList.iterator();
while (i.hasNext()){
Object object = i.next();
}
}
Run Code Online (Sandbox Code Playgroud)
另一种方法是将您转换List为array,迭代它们并List根据您的逻辑直接删除它们.
List<String> myList = new ArrayList<String>(); // You can use either list or set
myList.add("abc");
myList.add("abcd");
myList.add("abcde");
myList.add("abcdef");
myList.add("abcdefg");
Object[] obj = myList.toArray();
for(Object o:obj) {
if(condition)
myList.remove(o.toString());
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
378544 次 |
| 最近记录: |