java.util.ConcurrentModificationException由于意外修改
我正在实施A*算法,将给定数量的出租车分配给给定数量的客户:java.util.ConcurrentModificationException由于意外修改,java,Java,我正在实施A*算法,将给定数量的出租车分配给给定数量的客户: public SearchNode AStarSearch(List<Car> allCars, List<Customer> allCustomers) { // creates first node SearchNode firstNode = createFirstNode(allCars, allCustomers); open.add(firstNode); Sea
public SearchNode AStarSearch(List<Car> allCars, List<Customer> allCustomers) {
// creates first node
SearchNode firstNode = createFirstNode(allCars, allCustomers);
open.add(firstNode);
SearchNode currentNode;
while(true) {
currentNode = open.poll(); //error thrown here
if (currentNode.allCustomers.isEmpty()) break;
closed.add(currentNode);
SearchNode temp;
Iterator<Customer> itrCus = currentNode.allCustomers.iterator();
Iterator<Car> itrCar = currentNode.allCars.iterator();
while (itrCus.hasNext()) {
Customer currentCustomer = itrCus.next();
while (itrCar.hasNext()) {
Car currentCar = itrCar.next();
temp = new SearchNode(currentNode, currentCar, currentCustomer);
openUpdate(currentNode, temp);
}
}
}
return currentNode;
}
公共搜索节点AStarSearch(列出所有汽车,列出所有客户){
//创建第一个节点
SearchNode firstNode=createFirstNode(所有汽车、所有客户);
open.add(firstNode);
SearchNode当前节点;
while(true){
currentNode=open.poll();//此处抛出错误
如果(currentNode.allCustomers.isEmpty())中断;
closed.add(当前节点);
搜索节点温度;
迭代器itrCus=currentNode.allCustomers.Iterator();
迭代器itrCar=currentNode.allCars.Iterator();
while(itrCus.hasNext()){
Customer currentCustomer=itrCus.next();
while(itrCar.hasNext()){
Car currentCar=itrCar.next();
temp=新搜索节点(currentNode、currentCar、currentCustomer);
openUpdate(当前节点,临时);
}
}
}
返回当前节点;
}
现在,对于childrensearchnode,我想删除它所服务的客户。但这应该只发生在搜索节点内部
这就是SearchNode类中发生的情况:
public class SearchNode implements Comparable<SearchNode> {
List<Car> allCars;
List<Customer> allCustomers;
SearchNode parent;
public SearchNode(SearchNode parent, Car currentCar, Customer currentCustomer) {
// inheriting values from parent search node
this.allCars = parent.allCars;
this.allCustomers = parent.allCustomers;
this.parent = parent;
// now updating this node's values
this.allCustomers.remove(currentCustomer);
}
public类SearchNode实现可比较的{
列出所有汽车;
列出所有客户;
搜索节点父节点;
公共SearchNode(SearchNode父节点、Car currentCar、Customer currentCustomer){
//从父搜索节点继承值
this.allCars=parent.allCars;
this.allCustomers=parent.allCustomers;
this.parent=parent;
//现在正在更新此节点的值
此.allCustomers.remove(currentCustomer);
}
我检查了一些打印件,在的第二次迭代中(itrCar.hasNext())
,父级的allCustomer
列表缺少currentCustomer
编辑:我更想问:有人能告诉我为什么更改父节点的值吗?这可能是因为我还不了解整个java实际上是通过引用传递的。您应该创建一份
列表的副本,您想从中本地删除客户:
public SearchNode(SearchNode parent, Car currentCar, Customer currentCustomer) {
// inheriting values from parent search node
this.allCars = parent.allCars; // consider making a copy here too
// if required
this.allCustomers = new ArrayList<>(parent.allCustomers); // make a
// copy
this.parent = parent;
// now updating this node's values
this.allCustomers.remove(currentCustomer); // now you can safely
// remove currentCustomer
// without affecting
// parent.allCustomers
}
public SearchNode(SearchNode父节点、Car currentCar、Customer currentCustomer){
//从父搜索节点继承值
这也算是父母。
//如有需要
this.allCustomers=newarraylist(parent.allCustomers);//创建一个
//抄袭
this.parent=parent;
//现在正在更新此节点的值
this.allCustomers.remove(currentCustomer);//现在您可以安全地
//删除当前客户
//不影响
//家长。所有客户
}
所有包含对象(如列表)的变量本质上都是指针(挑剔者可能不同意确切的术语,但我相信这已经足够接近了)。所以当你说
this.allCustomers = parent.allCustomers
this.allCustomers和parent.allCustomers现在指向同一个列表对象。然后
this.allCustomers.remove(currentCustomer)
正在该列表上运行.remove(),该列表是父级的allCustomers…当前正在迭代。由于该列表已被修改,因此迭代失败
为了澄清对该问题的评论,“Java是100%按值传递的。对对象的引用是按值传递的。”这意味着您无法从C语言[1]实现函数“swap”,因为该函数获取副本(值)一个函数可以修改给定指针/引用的对象的属性,并使这些修改对传入对象的调用方可见,因为它们引用相同的对象。基元类型(int、boolean等)按值传递,但它们是不可变的(您可以说x=3,然后x=5,但没有3.changeValueTo(5)),因此差异在很大程度上可以忽略
···
[1] :这就是禁止使用不安全的类,该类可以直接访问内存。不要使用它,因为它会严重破坏东西。聪明的工程师可以永远使用它(例如,Java内部有时使用它),无论如何都不需要我的建议。“有人能告诉我如何更改父节点的值吗?”this.allCustomers.remove(currentCustomer);
,因为this.allCustomers=parent.allCustomers
。Java是100%按值传递的。对对象的引用是按值传递的。@AndyTurner是的,但我认为这是(在前面)将仅更改节点内的值。而不是仅为创建新对象实例而传递的父节点的值…?此时,我是否可以询问将ArrayList初始化为new ArrayList(parent.allCustomers);
与您的建议之间的区别?