Anylogic集合为空异常(java.util.NoSuchElementException)排查与解决
解决Anylogic中Van代理集合
route取元素时的NoSuchElementException异常 核心问题排查方向及修复方案
1. 字符串匹配错误:用==替代equals()导致订单加错Van
你在Source块里用v.Key == agent.VanKey匹配Van,如果Key和VanKey是字符串类型,这会导致匹配失败——Java中字符串==比较的是对象引用,不是内容。订单会被加到错误的Van(甚至可能没加到任何Van,此时findFirst返回null但Anylogic未报错),而你查看的Van并非当前取货的目标Van,所以出现“集合有元素但取货时为空”的矛盾。
修复代码:
Van targetVan = findFirst(vans, v -> v.Key.equals(agent.VanKey)); if(targetVan != null){ targetVan.route.addLast(agent); } else { trace("未找到匹配VanKey: " + agent.VanKey); // 加日志排查匹配失败情况 }
2. 仿真时序冲突:取货动作早于订单添加完成
Pickup块的触发时间戳可能早于对应Van的所有Order完成导入并加入集合的时间。虽然你在仿真运行后看到集合有元素,但触发取货的瞬间集合是空的,直接调用getFirst()/removeFirst()就会抛出异常。
修复方案:
- 在Pickup块的「触发条件」中添加集合非空判断:
!agent.route.isEmpty(),只有集合有元素时才执行取货动作。 - 调整Pickup块的时间戳设置,确保晚于对应Van所有订单的导入时间(可通过数据库订单时间戳关联配置)。
3. 集合未正确初始化或类型不匹配
检查Van代理中route集合的定义:
- 确保集合已初始化:在Van代理的属性窗口中,将
route的类型设为LinkedList<Order>或Queue<Order>,并勾选「初始化」选项;或者在Van的on startup代码中手动实例化:route = new LinkedList<>();。 - 避免使用不支持
getFirst()/removeFirst()的集合类型(比如ArrayList),如果用ArrayList,要改用get(0),但同样要先判断size() > 0。
4. 取元素时未做非空判断
无论哪种情况,取集合元素前必须先判断是否为空,这是避免NoSuchElementException的通用做法。
示例代码(Pickup块动作中):
if(!route.isEmpty()){ Order firstOrder = route.removeFirst(); // 执行首单配送逻辑,比如设置货车目的地等 } else { trace("Van " + Key + " 当前无待配送订单"); }
内容的提问来源于stack exchange,提问作者mpardi
相关产品推荐
相关产品推荐

