Anylogic中如何解决订单停车场分配时的java.lang.IndexOutOfBoundsException问题
问题原因
- 你赋值
arr_assignedOrderSet = pop_parkings.get(index).orderSet时,只是把集合的引用传递给了变量,并没有生成新的集合副本,两个变量指向的是内存里同一个ArrayList对象。 - 遍历过程中,
order.col_parking包含了当前已分配的停车场(也就是pop_parkings.get(index)),执行p.orderSet.remove(order)时,会直接修改你正在遍历的arr_assignedOrderSet对应的集合长度。 - 循环中
i持续递增,但集合的size()持续递减,每删一个元素,后续元素都会向前挪动一位,导致你直接跳过了下一个本该遍历的元素;当i增长到11时,集合长度也降到了11,循环条件i < arr_assignedOrderSet.size()不再成立,循环就提前终止了。如果把判断条件写死为22,当集合长度降到11时还在访问索引11的元素,就会抛出越界异常。
解决方案
有两种常用的修复方式,可按需选择:
方案1:遍历集合的副本,避免遍历和修改同一个集合
直接复制一份当前待处理的订单集合作为遍历对象,修改源集合不会影响遍历过程:
// 复制源集合生成独立的遍历副本 ArrayList<Order> arr_assignedOrderSet = new ArrayList<>(pop_parkings.get(index).orderSet); Parking assignedParking = pop_parkings.get(index); for(int i=0; i<arr_assignedOrderSet.size(); i++){ Order order = arr_assignedOrderSet.get(i); for(int j=0; j<order.col_parking.size(); j++){ Parking p = order.col_parking.get(j); // 可选优化:跳过当前已分配的停车场,无需移除它的订单记录 if(p == assignedParking){ continue; } p.orderSet.remove(order); } }
方案2:移除操作时跳过当前已分配的停车场,不修改正在遍历的集合
不需要额外复制集合,只需要在移除前判断当前停车场是不是订单最终分配的停车场,跳过它即可避免修改正在遍历的集合:
ArrayList<Order> arr_assignedOrderSet = pop_parkings.get(index).orderSet; Parking assignedParking = pop_parkings.get(index); for(int i=0; i<arr_assignedOrderSet.size(); i++){ Order order = arr_assignedOrderSet.get(i); for(int j=0; j<order.col_parking.size(); j++){ Parking p = order.col_parking.get(j); // 跳过已分配的停车场,不会修改当前遍历的集合 if(p == assignedParking){ continue; } p.orderSet.remove(order); } }
内容的提问来源于stack exchange,提问作者Yu LIU
相关产品推荐
相关产品推荐

