简体   繁体   English

iterator.remove() 中的 java.lang.IllegalStateException

[英]java.lang.IllegalStateException in iterator.remove()

Rocket class contains: canCarry (Item item)>checks if this item can be carried/ carry updates the weight with total weight. Rocket class 包含: canCarry (物品)>检查该物品是否可以携带/携带更新重量与总重量。

U2 class is child of Rocket contains: currentweight , maxWeight =18 tons Item class contains: name to be shipped & weight. U2 class 是 Rocket 的子代 包含:当前重量,最大重量 =18 吨 项目class包含:要运输的名称和重量。

In the method loadU2 I am trying to access a list of items and adding it into one rocket until maxWeight of that rocket is reached.loadU2方法中,我试图访问项目列表并将其添加到一个火箭中,直到达到该火箭的maxWeight For example I have 216 tons of items to carry returning a list of 12 ships.例如,我有 216 吨的物品要携带返回 12 艘船的清单。

It throws me java.lang.IllegalStateException error in the line iterator.remove() .它在iterator.remove()行中向我抛出java.lang.IllegalStateException错误。 I do not know how to go about it, but it looks like it is not allowing me to remove the items while iterating.我不知道如何 go 关于它,但看起来它不允许我在迭代时删除项目。

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)

Simplified example of what the code is doing: Assuming maxWeight for each ship = 11 tons ArrayList loadItems = [3,5,5,8,1,2,3,5] tons代码执行的简化示例:假设每艘船的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]

Please, rewrite your code by creating new ArrayList, instead of changing the existing list inside its own iterator:请通过创建新的 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;
} 

This is not the best solution, but to provide a better solution, you need to change the signature of public ArrayList<Rocket> loadU2(ArrayList<Item> loadItems)这不是最好的解决方案,但要提供更好的解决方案,您需要更改public ArrayList<Rocket> loadU2(ArrayList<Item> loadItems)的签名

You can try to improve your code by refactoring it.您可以尝试通过重构来改进您的代码。

Hint: right now your loadU2 method tries to do both things at the same time: change loadItems and create U2Ships .提示:现在你的loadU2方法试图同时做这两件事:改变loadItems并创建U2Ships This is a direct violation of the single responsibility principle .这直接违反了单一责任原则 Try to imagine the soldier who would try to shoot the gun and throw grenade at the same time.试着想象一个士兵会同时开枪和投掷手榴弹。 One thing at the time.当时有一件事。

The problem is here:问题在这里:

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

You are calling iterator.remove() within a loop.您正在循环中调用iterator.remove() If the condition tempShip.canCarry(tempItem) holds twice, you call iterator.remove() twice, and this is not allowed (the second time, the item is already removed).如果条件tempShip.canCarry(tempItem)成立两次,则调用iterator.remove()两次,这是不允许的(第二次,该项目已被删除)。

I don't know how the method canCarry is implemented, but note that if it is the case that tempShip.currentWeight<tempShip.weightLimit is true, but tempShip.canCarry(tempItem) is false, your loop will run forever.我不知道canCarry方法是如何实现的,但请注意,如果tempShip.currentWeight<tempShip.weightLimit为 true,但tempShip.canCarry(tempItem)为 false,则您的循环将永远运行。

use listIterator instead of Iterator.使用 listIterator 而不是 Iterator。

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

like used here.喜欢这里使用。

Remove elements from collection while iterating 迭代时从集合中删除元素

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;
} 

Thank you guys for the help, this should fix 2 problems: infinity, and the iterator.remove().谢谢你们的帮助,这应该解决 2 个问题:infinity 和 iterator.remove()。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM