【问题标题】:JAVA - Removing non iterator element from iterating listJAVA - 从迭代列表中删除非迭代器元素
【发布时间】:2016-07-19 03:29:54
【问题描述】:

我在遍历这个迭代器循环时遇到了一个问题,在这个循环中我遍历了 this.env 的每个元素,但是在这个列表中,想要删除所述列表的不同元素。当我尝试删除所述迭代列表的任何项目时,我收到此错误:java.util.ConcurrentModificationException,据我了解,这是由于修改迭代列表而不使用 iterator.remove ()。

代码:

public void envActions(IOHandler ioHandler, PlayerClass player){
    Iterator<WorldElement> worldElementIterator = this.env.iterator();
    while(worldElementIterator.hasNext()){
        WorldElement worldElement = worldElementIterator.next();
    //for(WorldElement worldElement:this.env){
        if(worldElement instanceof EntityClass){
            EntityClass entity=(EntityClass) worldElement;
            if(entity.nature.contains("hostile")){
                MonsterClass mEntity=(MonsterClass) entity;
                if(!(mEntity.attacks.size()*(Math.random()+0.25)>=mEntity.attacks.size())){
                    Double followerNum = (Math.random()*player.followers.size());
                    Integer followerNumInt=followerNum.intValue();
                    if(followerNumInt<2){
                        PlayerClass target=player;
                        Double attacknumD=mEntity.attacks.size()*Math.random();
                        Integer attacknum= attacknumD.intValue();
                        Integer playerarmor=player.getArmorValue();
                        int enemydamage=mEntity.attacks.get(attacknum).getDamage()*(1-(playerarmor/1000));
                        target.health=target.health-enemydamage;
                        ioHandler.printToConsole("\nThe "+mEntity.name+" attacked you with "+mEntity.attacks.get(attacknum).getAttack()+" and did "+mEntity.attacks.get(attacknum).getDamage()+" damage! you have "+player.health+" health left!");
                    } else {
                        FriendlyCreatureClass target=player.followers.get(followerNumInt);
                        Double attacknumD=mEntity.attacks.size()*Math.random();
                        Integer attacknum= attacknumD.intValue();
                        int enemydamage=mEntity.attacks.get(attacknum).getDamage();
                        target.health=target.health-enemydamage;
                        if(!target.isAlive()){
                            ioHandler.printToConsole("\nThe " + mEntity.name + " attacked " + target.name + " with " + mEntity.attacks.get(attacknum).getAttack() + " and did " + mEntity.attacks.get(attacknum).getDamage() + " damage! " + target.name+" died! Farewell "+target.name+".");
                            target.died(ioHandler, this, player, true);
                            //>>>> THIS IS WHERE I WOUlD LIKE TO REMOVE 'target' FROM THE env LIST <<<<
                        } else {
                            ioHandler.printToConsole("\nThe "+mEntity.name+" attacked "+target.name+" with "+mEntity.attacks.get(attacknum).getAttack()+" and did "+mEntity.attacks.get(attacknum).getDamage()+" damage! "+target.name+" has "+target.health+" health left!");
                        }
                    }
                }

请原谅我的编码技巧,因为我只是 java / Android 的初学者,但非常感谢任何建议!

提前致谢!

【问题讨论】:

  • 你为什么没有尝试 worldElementIterator.remove() ?
  • 这不会删除迭代器本身吗?我想删除列表中的自定义元素...
  • 不,我在下面为您回答。它删除最近访问的元素,在您的情况下,worldElement 已从集合中删除。迭代器没有被删除,它是元素。
  • 您正在尝试删除与Iterator 的当前元素 (worldElement) 不同的元素 (target)。这是一个非常不寻常的情况。这些元素在列表中如何相互关联?例如。 target 总是在 worldElement 的左边吗?
  • @PaulBoddington 是的,这正是我的问题,没有随机选择目标...

标签: java android iterator listiterator


【解决方案1】:

我认为它现在可以添加一个 toDelete 列表,检查迭代项是否已经在列表中,如果是,则跳过它,然后将其删除。

我还没有彻底检查错误,但现在没问题。 工作代码:

public void envActions(IOHandler ioHandler, PlayerClass player){
    List<WorldElement> toDelete=new ArrayList<>();
    Iterator<WorldElement> worldElementIterator = this.env.iterator();
    while(worldElementIterator.hasNext()){
        WorldElement worldElement = worldElementIterator.next();
    //for(WorldElement worldElement:this.env){
        if(worldElement instanceof EntityClass && !toDelete.contains(worldElement)){
            EntityClass entity=(EntityClass) worldElement;
            if(entity.nature.contains("hostile")){
                MonsterClass mEntity=(MonsterClass) entity;
                if(!(mEntity.attacks.size()*(Math.random()+0.25)>=mEntity.attacks.size())){
                    Double followerNum = (Math.random()*player.followers.size());
                    Integer followerNumInt=followerNum.intValue();
                    if(followerNumInt<2){
                        PlayerClass target=player;
                        Double attacknumD=mEntity.attacks.size()*Math.random();
                        Integer attacknum= attacknumD.intValue();
                        Integer playerarmor=player.getArmorValue();
                        int enemydamage=mEntity.attacks.get(attacknum).getDamage()*(1-(playerarmor/1000));
                        target.health=target.health-enemydamage;
                        ioHandler.printToConsole("\nThe "+mEntity.name+" attacked you with "+mEntity.attacks.get(attacknum).getAttack()+" and did "+mEntity.attacks.get(attacknum).getDamage()+" damage! you have "+player.health+" health left!");
                    } else {
                        FriendlyCreatureClass target=player.followers.get(followerNumInt);
                        Double attacknumD=mEntity.attacks.size()*Math.random();
                        Integer attacknum= attacknumD.intValue();
                        int enemydamage=mEntity.attacks.get(attacknum).getDamage();
                        target.health=target.health-enemydamage;
                        if(!target.isAlive()){
                            ioHandler.printToConsole("\nThe " + mEntity.name + " attacked " + target.name + " with " + mEntity.attacks.get(attacknum).getAttack() + " and did " + mEntity.attacks.get(attacknum).getDamage() + " damage! " + target.name + " died! Farewell " + target.name + ".");
                            target.died(ioHandler, this, player, false);
                            toDelete.add(target);
                        } else {
                            ioHandler.printToConsole("\nThe "+mEntity.name+" attacked "+target.name+" with "+mEntity.attacks.get(attacknum).getAttack()+" and did "+mEntity.attacks.get(attacknum).getDamage()+" damage! "+target.name+" has "+target.health+" health left!");
                        }
                    }
                }
    for(WorldElement worldElement:toDelete){
        this.env.remove(worldElement);
    }
    return;

感谢您的快速回复!

【讨论】:

    【解决方案2】:

    如果您出于某种原因不使用迭代器,则可以在迭代集合时收集要在集合中删除的元素,并在循环之后迭代集合并从原始集合中删除元素。

    请注意,这仅适用于小型集合。

    HashSet toDelete = new HashSet();
    
    for (...) {
        if (...)
           toDelete.add(item);
    }
    // end for
    
    foreach (item in toDelete) {
        // delete from original collection
    }
    

    否则,您可以在迭代器上调用 remove()。

    【讨论】:

    • 但是如果我不删除每个循环后需要删除的元素,它会再次触发循环并执行操作,即使它甚至不应该存在?
    • 他不应该这样做,这没有任何意义。如果他已经在使用迭代器,只需使用正确的功能
    • @LucasCrawford Iterator.remove() 如果不删除迭代中刚刚访问过的元素,则将不起作用。
    • @TheFloppyToast 那么您还应该检查元素是否在toDelete 中并在迭代过程中跳过它。这确实可能是您能够解决问题的唯一方法。
    • @LouisWasserman 是的,成功了!如果您好奇,我在下面发布了工作代码 sn-p
    猜你喜欢
    • 2013-11-25
    • 1970-01-01
    • 2018-07-18
    • 1970-01-01
    • 2019-09-11
    • 2021-05-05
    • 2011-10-16
    • 2014-12-16
    • 2013-01-23
    相关资源
    最近更新 更多