Telegram Bot Java遇ConcurrentModificationException及用户列表异常
问题分析与修复
核心问题
- ConcurrentModificationException异常:遍历
users列表时直接调用users.add(buddy),触发集合快速失败机制——ArrayList这类集合在迭代过程中不允许添加/删除元素的结构性修改。 - 逻辑错误导致重复添加:当前遍历逻辑会对列表中每个不匹配的用户都插入新Buddy,哪怕列表里已经有匹配的用户,也会继续给其他不匹配项执行添加操作,完全达不到“唯一实例”的要求。
- 列表显示null:基本是
Buddy类的toString()方法未正确实现,输出时无法展示属性值导致显示null。
修复步骤
1. 修正遍历与添加逻辑
先判断用户是否存在,确认不存在后再添加,避免遍历中修改集合:
private void addUser(String name, long chatId) { boolean userExists = false; // 遍历检查用户是否已存在 for (Buddy user : users) { if (name.equals(user.getName()) && chatId == user.getNameId()) { System.out.println("Exists"); userExists = true; break; // 找到匹配项直接停止遍历,提升效率 } } // 不存在则添加新用户 if (!userExists) { users.add(new Buddy(name, chatId)); } System.out.println(users.toString()); }
2. 解决并发修改异常
如果消息处理是多线程场景,users集合需要保证线程安全:
- 方案一:改用线程安全集合
CopyOnWriteArrayList,它支持遍历的同时修改集合,不会抛出ConcurrentModificationException。 - 方案二:给集合操作加同步锁:
private void addUser(String name, long chatId) { synchronized (users) { boolean userExists = false; for (Buddy user : users) { if (name.equals(user.getName()) && chatId == user.getNameId()) { System.out.println("Exists"); userExists = true; break; } } if (!userExists) { users.add(new Buddy(name, chatId)); } System.out.println(users.toString()); } }
3. 修复列表显示null问题
检查Buddy类的toString()方法,确保正确输出属性内容:
public class Buddy { private String name; private long nameId; // 构造方法、Getter等省略 @Override public String toString() { return "Buddy{name='" + name + "', nameId=" + nameId + "}"; } }
优化建议
用HashMap存储用户(以唯一的chatId为键),判断用户是否存在的效率从O(n)降到O(1),更适合高频场景:
// 用线程安全的ConcurrentHashMap适配多线程环境 private Map<Long, Buddy> userMap = new ConcurrentHashMap<>(); private void addUser(String name, long chatId) { if (userMap.containsKey(chatId)) { System.out.println("Exists"); } else { userMap.put(chatId, new Buddy(name, chatId)); } System.out.println(userMap.values().toString()); }
内容的提问来源于stack exchange,提问作者kikichs
相关产品推荐
相关产品推荐

