英文:
ConcurrentModificationException but I am not modifying the Collection I am iterating
问题
我正在迭代一个消息对象列表,试图获取所有会话,其中会话表示在上一条消息之后的 20 分钟内发送了后续消息。
第一次迭代运行正常,在第二次迭代中,我遇到了 **java.util.ConcurrentModificationException** 异常
尽管我没有修改我正在迭代的消息列表。请参阅下面的代码。
public List<Chat> getAllConversations(int allowedMinutes) {
List<Chat> result = new ArrayList<>();
Chat currentConvo = new Chat();
List<Message> ml = this.getMessageList();
for (Message m : ml) {
if (currentConvo.getMessageList().isEmpty() || m.getDateTime().until(currentConvo.getMessageList().get(currentConvo.getMessageList().size() - 1).getDateTime(), ChronoUnit.MINUTES) <= allowedMinutes) {
currentConvo.addMessage(m);
continue;
}
if (currentConvo.getAllParticipants().size() > 1) {
// only if more than one participant is involved it is a conversation
result.add(currentConvo);
}
// not more than one person involved and also last message is too long ago -> discard the current conversation
currentConvo = new Chat();
currentConvo.addMessage(m);
}
return result;
}
这是错误消息:
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.chatstats, PID: 22185
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.next(ArrayList.java:860)
at com.example.chatstats.Chat.getAllConversations(Chat.java:188)
at com.example.chatstats.MainActivity.onClickShowResults(MainActivity.java:169)
at com.example.chatstats.MainActivity$9.onClick(MainActivity.java:152)
at android.view.View.performClick(View.java:6256)
at android.view.View$PerformClick.run(View.java:24701)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
I/zygote: WaitForGcToComplete blocked for 14.815ms for cause HeapTrim
Disconnected from the target VM, address: 'localhost:8622', transport:
'socket'
感谢您的回复。
英文:
I am iterating over a list of Message objects with the attempt to get all conversations, where conversation means that a subsequent message was sent within 20 Minutes after the previous message.
The first iteration works fine, and in the second one I am getting a java.util.ConcurrentModificationException
Even though I am not modifying the Message List I am iterating. See code below.
public List<Chat> getAllConversations(int allowedMinutes) {
List<Chat> result = new ArrayList<>();
Chat currentConvo = new Chat();
List<Message> ml = this.getMessageList();
for (Message m : ml) {
if (currentConvo.getMessageList().isEmpty() || m.getDateTime().until(currentConvo.getMessageList().get(currentConvo.getMessageList().size() - 1).getDateTime(), ChronoUnit.MINUTES) <= allowedMinutes) {
currentConvo.addMessage(m);
continue;
}
if (currentConvo.getAllParticipants().size() > 1) {
// only if more than one participant is involved it is a conversation
result.add(currentConvo);
}
// not more than one person involved and also last message is too long ago -> discard the current conversation
currentConvo = new Chat();
currentConvo.addMessage(m);
}
return result;
}
This is the Error Message:
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.chatstats, PID: 22185
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.next(ArrayList.java:860)
at com.example.chatstats.Chat.getAllConversations(Chat.java:188)
at com.example.chatstats.MainActivity.onClickShowResults(MainActivity.java:169)
at com.example.chatstats.MainActivity$9.onClick(MainActivity.java:152)
at android.view.View.performClick(View.java:6256)
at android.view.View$PerformClick.run(View.java:24701)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
I/zygote: WaitForGcToComplete blocked for 14.815ms for cause HeapTrim
Disconnected from the target VM, address: 'localhost:8622', transport:
'socket'
Thank you for your replies.
答案1
得分: 2
但是你在例外情况下并没有撒谎。有可能是另一个线程在执行这个操作;更有可能的情况是你的for循环中的某行代码引起了变动。例如,也许addMessage
命令会确定消息已经属于哪个聊天,并将其从那个聊天中移除 - 也就是从你这边移除,改变了列表。
编辑:正如Andreas所评论的,另一个可能的解释是你错误地将messageList
字段设为了static
。在这种情况下,所有不同的聊天对象共享一个列表,因此,向新创建的聊天对象添加消息仍然会将其添加到单一的全局列表中。解决办法是:将其设为非静态。
英文:
But you are; the exception is not lying to you. It is possible another thread is doing it; it is more likely one of the lines in your forloop is causing a change. For example, perhaps the addMessage
command figures out which Chat the message is already a part of, and removes it from there – i.e. from you, changing the list.
EDIT: As Andreas has commented, another plausible explanation is that you've accidentally made the messageList
field static
. In that case, all the different chat objects share a single list, and thus, adding a message to a newly created Chat object is still adding it to the single global list. Solution if this is the case: Make it non-static.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论