java.lang.IllegalStateException 在 iterator.remove()

java.lang.IllegalStateException in iterator.remove()

Rocket class contains: canCarry(Item item)>检查这个物品是否可以携带/ carry 用总重量更新权重。

U2 class 是 Rocket 的子项包含:currentweightmaxWeight =18吨 项目 class 包含:要运送的名称和重量。

在方法 loadU2 中,我试图访问一个项目列表并将其添加到一个火箭中,直到该火箭的 maxWeight到达 。 例如我有 216 吨的物品要运载返回 12 艘船的清单。

它在行 iterator.remove() 中抛出 java.lang.IllegalStateException 错误。我不知道该怎么做,但看起来它不允许我在迭代时删除项目。

public ArrayList<Rocket> loadU2(ArrayList<Item> loadItems){
    //list of ships
    ArrayList<Rocket> U2Ships = new ArrayList<Rocket>();
    for(Iterator<Item> iterator = loadItems.iterator(); iterator.hasNext();) {      
        //create a new ship
        Rocket tempShip = new U2();
        Item tempItem = iterator.next();
        //loop over items check if it can be filled then remove the item that was filled.
        while(tempShip.currentWeight<tempShip.weightLimit) {
            if(tempShip.canCarry(tempItem)){
                tempShip.carry(tempItem);
                iterator.remove();
            }           
        }
        U2Ships.add(tempShip);
    }
    return U2Ships;
}   


Exception in thread "main" java.lang.IllegalStateException
    at java.base/java.util.ArrayList$Itr.remove(ArrayList.java:980)
    at Simulation.loadU1(Simulation.java:35)
    at Main.main(Main.java:14)

代码作用的简化示例: 假设每艘船的 maxWeight = 11 吨 ArrayList loadItems = [3,5,5,8,1,2,3,5] 吨

 - Ship[1]=[3,5,1,2]
 - new list to iterate over >> [5,8,3,5]
 - Ship[2]=[5,3]
 - new list to iterate over >> [8,5]
 - Ship[3]=[8]
 - new list to iterate over >> [5]
 - Ship[4]=[5]

使用 listIterator 而不是 Iterator。

ListIterator<Book> iter = books.listIterator();
while(iter.hasNext()){
    if(iter.next().getIsbn().equals(isbn)){
        iter.remove();
    }
}

喜欢这里使用。

Remove elements from collection while iterating

请通过创建新的 ArrayList 来重写您的代码,而不是在它自己的迭代器中更改现有列表:

public ArrayList<Rocket> loadU2(ArrayList<Item> loadItems){
    //list of ships
    ArrayList<Rocket> U2Ships = new ArrayList<Rocket>();
    ArrayList<Item> updatedLoadItems = new ArrayList<Item>();
    for(Iterator<Item> iterator = loadItems.iterator(); iterator.hasNext();) {      
        //create a new ship
        Rocket tempShip = new U2();
        Item tempItem = iterator.next();
        //loop over items check if it can be filled then only leave the load item that was not fully filled.
        boolean addLoadItem = true;
        while(tempShip.currentWeight<tempShip.weightLimit) {
            if(tempShip.canCarry(tempItem)){
                tempShip.carry(tempItem);
                addLoadItem = false;
            }         
        }
        if (addLoadItem) {
          updatedLoadItems.add(tempItem);
        };
        U2Ships.add(tempShip);
    }
    loadItems.removeAll();
    loadItems.addAll(updatedLoadItems);
    return U2Ships;
} 

这不是最好的解决方案,但为了提供更好的解决方案,您需要更改public ArrayList<Rocket> loadU2(ArrayList<Item> loadItems)

的签名

您可以尝试通过重构来改进您的代码。

提示: 现在你的 loadU2 方法试图同时做这两件事:改变 loadItems 并创建 U2Ships。这直接违反了单一责任原则。试想一下,士兵会尝试同时开枪和投掷手榴弹!当时一件事。

问题出在这里:

while(tempShip.currentWeight<tempShip.weightLimit) {
    if(tempShip.canCarry(tempItem)){
        tempShip.carry(tempItem);
        iterator.remove();
    }           
}

您正在循环中调用 iterator.remove()。如果条件 tempShip.canCarry(tempItem) 成立两次,您调用 iterator.remove() 两次,这是不允许的(第二次,该项目已被删除)。

我不知道方法canCarry是如何实现的,但请注意,如果tempShip.currentWeight<tempShip.weightLimit为真,而tempShip.canCarry(tempItem)为假,你的循环将运行永远。

public ArrayList<Rocket> loadU2(ArrayList<Item> loadItems){
    //list of ships
    int shipNum=0;
    int itemsloaded=0;
    ArrayList<Rocket> U2Ships = new ArrayList<Rocket>();
    while(!loadItems.isEmpty()) {      
        System.out.println("number of ships created: "+shipNum++);
        //create a new ship
        Rocket tempShip = new U2();
        
        //loop over items check if it can be filled then only leave the load item that was not fully filled.
     
        while(iterator.hasNext()) {  
            Item tempItem = iterator.next();
            if(tempShip.canCarry(tempItem)){
                System.out.println("number of items loaded: "+(itemsloaded++));
                tempShip.carry(tempItem);
                iterator.remove();                                      
             
           } 
        }
        
        U2Ships.add(tempShip);
    }

    return U2Ships;
} 

谢谢大家的帮助,这应该可以解决 2 个问题:无穷大和 iterator.remove()。