IndexOutOfBoundsException:我在 while 循环中看不到

IndexOutOfBoundsException: I don't see in my while loop

我一直卡在这个我无法理解的 IndexOutOfBoundsException 上,我不明白为什么它指向我的 while 循环。关于做什么的任何建议?顺便说一句,该方法是一个循环调度模拟器,它似乎可以与我的一个测试文件完美配合,但不能与另一个测试文件配合使用。

public void roundRobin2(ArrayList<Jobs> c, int startSize)
{   
    //int n = 0;
    double counter = 0;
    double compTime = 0;
    while(!c.isEmpty())
    {
        int i = 0;
        System.out.println(c);
        for(i = 0; i < c.size(); i++)
        {
            if((c.get(i).jobTime) >= 2)
            {
                c.get(i).jobTime -= 2;
                counter += 2;

                if((c.get(i).jobTime) == 0)
                {
                    compTime += counter;
                }
            }
            else
            {
                (c.get(i).jobTime) -= 1;        
                counter += 1;

                if((c.get(i).jobTime) == 0)
                {
                    compTime += counter;
                }
            }
            //System.out.print("-" + c.get(i).jobName + "-" + counter);
            //n++;
            //if(n%10 == 0)
            //{
                //System.out.println("\n");
            //}
        }
        for(i = 0; i < c.size(); i++)
        {
            while(!c.isEmpty() && (c.get(i).jobTime) == 0)
            {
                c.remove(i);
            }       
        }
    }
    System.out.println("\n\nAverage completion times: "+ compTime + "/" + startSize +" = " + ((compTime)/startSize));
}

异常堆栈跟踪:

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 7, Size: 7
    at java.util.ArrayList.rangeCheck(Unknown Source)
    at java.util.ArrayList.get(Unknown Source)
    at cs431.edu.cpp.Main.roundRobin2(Main.java:143)

您正在删除正在迭代的 collection 中的项目,这非常糟糕,您永远不应该这样做。您可以使用具有 remove 方法的 Iterator 来执行此操作(但这很少有效),或者制作 collection 的临时副本。顺便说一句 round-robin 可以更容易地实施。

这个方案使用了一个LinkedList,因为在头部移除和在尾部插入都是O(1),这样既高效又安全。我还压缩了你的一些逻辑作为奖励:

public void roundRobin2(List<Jobs> jobs, int startSize) {
    double counter = 0;
    double compTime = 0;

    Deque<Jobs> uncompletedJobs = new LinkedList<>(jobs);
    while (!uncompletedJobs.isEmpty()) {
        Job job = uncompletedJobs.pop();
        int taskTime = job.jobTime >= 2 ? 2 : 1;
        job.jobTime -= taskTime;
        counter += taskTime;
        if (job.jobTime == 0) {
            compTime += counter;
        } else {
             uncompletedJobs.addLast(job);
        }
    }
    jobs.clear();
    System.out.println("\n\nAverage completion times: "+ compTime + "/" + startSize +" = " + ((compTime)/startSize));
}

您的代码:

while(!c.isEmpty() && (c.get(i).jobTime) == 0)
{
    c.remove(i);
}
如果 i 正在删除最后一个元素,但不会导致列表变空,

将失败。改用这个:

while (i < c.size() && c.get(i).jobTime == 0)
{
    c.remove(i);
}

更新

您的代码将通过使用 for (obj : list) 循环进行大量清理,您应该使用 Iterator 删除元素。这是清理后的代码:

public static void roundRobin2(ArrayList<Jobs> c, int startSize)
{
    double counter = 0;
    double compTime = 0;
    while (! c.isEmpty())
    {
        System.out.println(c);
        for (Jobs jobs : c)
        {
            if (jobs.jobTime >= 2)
            {
                jobs.jobTime -= 2;
                counter += 2;
            }
            else
            {
                jobs.jobTime -= 1;
                counter += 1;
            }
            if (jobs.jobTime == 0)
            {
                compTime += counter;
            }
        }
        for (Iterator<Jobs> jobsIter = c.iterator(); jobsIter.hasNext(); )
        {
            Jobs jobs = jobsIter.next();
            if (jobs.jobTime == 0)
            {
                jobsIter.remove();
            }
        }
    }
    System.out.println("\n\nAverage completion times: " + compTime + "/" + startSize + " = " + (compTime / startSize));
}