从包含子类和超类项的arraylist中删除项

时间:2013-07-04 09:35:29

标签: java

我有一个arraylist'items',它包含来自超类的项目以及来自其子类的项目。

    for (Item item : items)
    {
        if (item.getLocation() == location)
        {   
            System.out.println(item.getDescription() + " is in this location");
            if (item instanceof Monster)
            {
                Monster monster = (Monster)item; 
                if (monster.hasDied())
                {
                    System.out.println(monster.getDescription() + " has been defeated!");
                    items.remove(monster);     
                }
            }   
        }   
    } 

如果发现怪物已经死亡,我试图从怪物中移除怪物。所有这些方法都有效,我知道你在foreach循环中不能从arraylist中删除项目,如上所示。我以前使用下面的代码从arraylist中删除怪物,但是当有一个单独的'items'和'monsters'arraylist时。它们现在都在相同的'items'arraylist中,因为'Monster'类是'Item'类的子类。

    Iterator<Monster> iter = monsters.iterator();
    while (iter.hasNext()) 
    {
        Monster monster = iter.next();
        if (monster.hasDied())
        {
            if (monster.getLocation() == location)
            {
                System.out.println(monster.getDescription() + " has been defeated!");
                iter.remove();
            }
            else
            {
               iter.remove(); 
            }
        }
    }

无论如何我可以采用任何一种方法从arraylist中移除指定的怪物吗?

感谢您的帮助!

4 个答案:

答案 0 :(得分:3)

绝对 - 您需要做的就是结合您拥有的两种方法:

  • 使用Iterator按照第二种方法中的方式迭代列表;
  • 在第一种方法中检查当前item的方式Monster。这个组合可以让你使用迭代器找到它Monsterremove

以下是如何做到这一点:

Iterator<Item> iter = items.iterator();
while (iter.hasNext()) 
{
    Item item = iter.next();
    if (item instanceof Monster)
    {
        Monster monster = (Monster)item; 
        if (monster.hasDied())
        {
            if (monster.getLocation() == location)
            {
                System.out.println(monster.getDescription() + " has been defeated!");
                iter.remove();
            }
            else
            {
               iter.remove(); 
            }
        }
    }
}

答案 1 :(得分:1)

避免类型检查的多态方法如下。在此方法中,特定Item是否为Monster并不重要,因为可以检查所有Item的有效性,Item本身知道它是如何做的无效

public class Item {
    //assorted item methods


    public boolean isStillValid(){
        return true; //by default items remain valid
    }

    public String getDescription(){
        return "SomeItem"; //I assume you can provide a better description than this, I don't know your usage case so can't comment
    }

    public String getNoLongerValidText(){
        return getDescription() + "is no longer valid"; //items that actually become invalid should override this and give a better text
    }
}


public class Monster extends Item{

    //assorted extra Monster Methods

    int health=100;

    public boolean isStillAlive(){
        if (health<=0){
            return false;
        }else{
            return true;
        }
    }

    @Override
    public boolean isStillValid() {
        return isStillAlive();
    }

    @Override
    public String getDescription() {
        return "MonsterName";
    }

    @Override
    public String getNoLongerValidText() {
        return getDescription() + "has died";
    }

}

由于可以检查所有项目的有效性,因此特定ItemMonster

不再重要
Iterator<Item> iter = items.iterator();
while (iter.hasNext()) 
{
    Item item = iter.next();
    if (item.isStillValid()==false)
    {
        System.out.println(item.getNoLongerValidText());
        iter.remove();
    }
}

这是特别好的,因为当其他Item(例如只有一定数量用途的药水(Potion extends Item)也可能无效时,它可以很好地扩展。

答案 2 :(得分:0)

如您所知,在迭代集合时无法删除项目。因此,您可以做的是在迭代和检查其状态时创建要删除的对象的列表(让它调用toRemoveObjList)。完成迭代后,您应该有一个需要删除的所有对象的列表。然后简单地调用

list.removeAll(toRemoveObjList);

供参考,javadocs for removeAll(Collection c)

http://docs.oracle.com/javase/6/docs/api/java/util/AbstractCollection.html#removeAll(java.util.Collection)

答案 3 :(得分:0)

我不确定你想要实现什么,但为什么你不会这么简单地写它:

    for (Iterator<Item> iter = items.iterator(); iter.hasNext();) {
            Item item = iter.next();
            if (item instanceof Monster) {
                    Monster monster = (Monster) item;
                    if (monster.hasDied()) {
                        if (monster.getLocation() == location) {
                            System.out.println(monster.getDescription() + " has been defeated!");
                        }
                        iter.remove();
                    }
            }
     }