当前位置: 首页 > 知识库问答 >
问题:

ArrayList中仅有对象的ArrayList索引越界异常

赵雅懿
2023-03-14

我知道这个问题以前可能被问过很多次,但我有一个问题,我找不到一个特别针对我的问题的解决方案。

问题如下:

我有两个火箭和射弹的阵列清单,它们之间的碰撞被检查。当它们碰撞时,两者都被移除。问题是,当arraylist中唯一的火箭被击中时,异常发生了,我不知道如何阻止它发生。

java.lang.IndexOutOfBoundsException: Index: 3, Size: 3
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at adam.miszczak.defendthebase.level.Level.collision(Level.java:158)
at adam.miszczak.defendthebase.level.Level.tick(Level.java:144)
at adam.miszczak.defendthebase.Game.tick(Game.java:124)
at adam.miszczak.defendthebase.Game.run(Game.java:104)
at java.lang.Thread.run(Unknown Source)

碰撞方法+ArrayLists:

public static ArrayList<Projectile> projectiles = new ArrayList<Projectile>();
private static ArrayList<Rocket> rockets = new ArrayList<Rocket>();

private void collision(){
    for(int i = 0; i < rockets.size(); i++){
        for(int j = 0; j < projectiles.size(); j++){
            try{
                if(rockets.get(i).bounds().intersects(projectiles.get(j).bounds())){
                    projectiles.remove(j);
                    rockets.get(i).die();
                    stats.addScore(rockets.get(i));
                    Particle p = new Particle(20, 20, 20, 50);
                    particles.add(p);
                }
            }catch(IndexOutOfBoundsException e){
                e.printStackTrace();
            }
        }
    }
}

删除和添加方法:

private void remove(ArrayList<Projectile> projectiles, ArrayList<Rocket> rockets){
    for(int i = 0; i < rockets.size(); i++){
        if(rockets.get(i).getVisible()){ rockets.remove(i); rocketsOnScreen--; }
    }

    for(int i = 0; i < projectiles.size(); i++){
        if(projectiles.get(i).isRemoved()){ projectiles.remove(i);}
    }

    for(int i = 0; i < planes.size(); i++){
        if(planes.get(i).isRemoved()){ planes.remove(i); planesOnLevel--;}
    }
}

private void spawnRocket(int rocketType, int x, ArrayList<Rocket> rockets) {
    switch (rocketType) {
        case ROCKET_NORMAL:
            rockets.add(new NormalRocket(x, -10, 80, 0, 2));
            rocketsSpawned++;
            rocketsOnScreen++;
            break;
        case ROCKET_FIRE:
            if(difficulty > 1 && random.nextInt(100) > fireRocketSpawn){
                    rockets.add(new FireRocket(x, -10, 70, 0, 2));
                    rocketsSpawned++;
                    rocketsOnScreen++;
            }else{
                return;
            }
            break;
        case ROCKET_ZIPPER:
            if(difficulty > 2 && random.nextInt(100) > zipperRocketSpawn){
                rockets.add(new ZipperRocket(x, -10, 40, 0, 4));
                rocketsSpawned++;
                rocketsOnScreen++;
            }else{
                return;
            }
            break;
        case ROCKET_TANK:
            if(difficulty > 3 && random.nextInt(100) > tankRocketSpawn){
                rockets.add(new TankRocket(x, -10, 130, 0, 1));
                rocketsSpawned++;
                rocketsOnScreen++;
            }else{
                return;
            }
            break;
    }
} 

注意:rocket.die()基本上只是删除火箭,与remove方法的方式相同。

共有1个答案

长孙兴德
2023-03-14

在对列表进行迭代时,不能使用迭代器以外的任何内容移除。想象一下后果;您正在遍历元素并删除元素n。所有其他元素都向下移动一个来填补空白。您接受元素n+1,现在是开始循环时的元素n+2。并且列表小了一个元素,所以您的边界检查现在是错误的。通过这种方式,您可能会遇到各种难以跟踪的bug。

在Java中,如果您使用正确的语法--即增强的foreach循环,那么如果您在迭代时尝试从列表中添加/删除,您将得到正确的错误--您将得到ConcurrentModificationException

要修复您的方法,1)删除所有索引。您正在滥用它们,它们是不必要的(现在,在每次迭代中,您会从每个列表中获得相同的元素吗?)。2)为内部循环使用一个实际的迭代器,这样您就可以调用iterator.remove列表中删除最后返回的元素。因为这是通过迭代器完成的,所以不会导致错误:

private void collision() {
    for (final Rocket rocket : rockets) {
        final Iterator<Projectile> iter = projectiles.iterator();
        while (iter.hasNext()) {
            final Projectile projectile = iter.next();
            if (rocket.bounds().intersects(projectile.bounds())) {
                rocket.die();
                stats.addScore(rocket);
                Particle p = new Particle(20, 20, 20, 50);
                particles.add(p);
                iter.remove();
            }
        }
    }
}
 类似资料:
  • 我有一个ArrayList,里面有一堆MyObject对象。我想在我的对象中保留一个整数字段,它是ArrayList中这个对象的键,这样我就可以很容易地得到这个元素在ArrayList中的位置。 当我从这个ArrayList中删除一个对象时,会出现问题,因为索引会向左移动。避免这个问题的最佳方法是什么? 我应该不删除元素,而是用null覆盖它们(这样索引就不会移位),还是应该在删除一次之后遍历Ar

  • 我正在为学校写一个充当收银机的程序。我要求输入项目的价格,并将它们播放到一个正在进行的ArrayList中,直到用户输入-1或0。0是在错误的情况下重新输入以前的价格,-1终止循环。 我得到了 我在Eclipse中运行Java11。 在不使用该方法的情况下,代码运行良好,因为我减少了计数器,并且在循环的下一次迭代中,无论是否删除了以前的数组位置,都将覆盖它。方法本身被设置为删除ArrayList.

  • 在运行Android TF Detect演示并使用我重新训练的3类ssd_mobilenet_v1_coco模型时,我的TF Detect演示崩溃,给出一个IndexOutOfBoundException 12-26 17:53:13.931 224 29-25212/org.tensorflow.demo E/AndroidRuntime:致命异常:推断进程:org.tensorflow.dem

  • 对于我当前的项目,我必须搜索ArrayList of ZipCode对象,以便找到距离用户输入的int zip最远的ZipCode。 下面是编写我遇到问题的方法的说明:public ZipCode findfurtwest(int-pZip)-查找距离提供的邮政编码最远的ZipCode。如果未找到邮政编码,则返回null。例如,距离邮政编码75234最远的是ADAK,AK 99546。 在我的代码

  • 问题内容: 可以说我有一堂课 我将一些数据对象添加到ArrayList中: 为什么indexOf找不到这个?: indexOf是否比我自己遍历整个数组列表更好?还是我错过了一些东西。 问题答案: 该方法 不 经过整个列表。这是Java 7源代码的摘录: 让Java通过它比自己编写它更好。只要确保您的方法足以找到所需的对象即可。您还需要覆盖。 我不会写出您的方法,但是我建议您至少: 检查是否为空 测

  • 我有一个ArrayList,从ArrayList的末尾(即使用add(object)方法)以串行方式(即逐个)填充Integer类型的对象。每次我这样做,ArrayList中的其他对象都会左移一个索引。 在我的代码中,我想在ArrayList中找到一个随机对象的索引。我想避免使用indexOf方法,因为我有一个非常大的ArrayList,循环将花费大量时间。有什么解决办法吗?如何在某些数据结构中保