0

I'm reviewing for the AP Computer Science A exam, and the code I wrote is a little different from the answer. Do you think you could check if each outputs the same result?

Objective: To remove a Cookie Order of a specific type from the CookieOrder ArrayList order, and return the number of boxes removed. Please assume that all methods work as suggested.

Answer:

public int removeVariety(String cookieVar)
{
 int boxesRemoved = 0;

 for (int i = orders.size() - 1; i >= 0; i--)
 {
 if (cookieVar.equals(orders.get(i).getVariety()))
boxesRemoved += orders.remove(i).getNumBoxes();
 }

return boxesRemoved; }

What I put:

public int removeVariety(String cookieVar)
{
    String cookieType = cookieVar;
    int totalRemoved = 0;

    for(CookieOrder boxes : this.order)
    {
        String type = boxes.getVariety();
        int totalBoxesCookieOrder = boxes.getNumBoxes();
        if(type.equals(cookieType))
        {
            totalRemoved += totalBoxesCookieOrder;
            this.order.remove(boxes);
        }
    }

    return totalRemoved;
}

Would this still work? Alternatively, if you would like to grade me, here's the scoring rubric (question 1, part B). I appreciate the help; the test is tomorrow and I'm super nervous.

4

3 回答 3

3

这还能用吗?

您的代码将失败,ConcurrentModificationException因为您在迭代集合时正在修改集合。

模型答案通过使用索引而不是Iterator... 并从列表的尾部到头部工作来避免这种情况。

避免 CME 问题的另一种方法是使用显式迭代器,并使用该Iterator.remove()方法进行删除。(这将适用于 anArrayList或 a LinkedList,但一些更奇特的列表类型可能会返回由于某种原因Iterator不支持的 an 。)remove()

于 2013-05-07T01:00:33.643 回答
2

正如其他人所提到的,这会抛出一个ConcurrentModificationException,因为您在迭代它时从列表中删除了一个项目。

一种安全的方法是使用迭代器。是所有集合(包括s)必须提供Iterator的内置类。ArrayList迭代器为您提供了一种遍历列表的方法(很像for您使用的 -loop),但也允许您安全地从集合中删除元素。

ArrayList首先从'iterator方法获取迭代器。Like ArrayList,Iterator通用的——也就是说,它是一个Iterator<CookieOrder>,而不仅仅是一个Iterator.

Iterator<CookieOrder> iterator = order.iterator();

该类Iterator有两个关键方法:hasNextnext. 您要检查每个项目,直到没有剩余项目为止。每当您调用next时,都会将迭代器推进一个。您的代码如下所示:

// Make sure there are still items in the array.
while (iterator.hasNext()) {
    // Get the item.
    CookieOrder o = iterator.next();

    // do something with o
}

专门针对您的问题:

Iterator<CookieOrder> iterator = order.iterator();
while (iterator.hasNext()) {
    // Get the boxes cookie order.
    CookieOrder boxes = iterator.next();

    // Perform the same check as before.
    String type = boxes.getVariety();
    int totalBoxesCookieOrder = boxes.getNumBoxes();
    if(type.equals(cookieType))
    {
        totalRemoved += totalBoxesCookieOrder;

        // Here's where we want to remove it.
        //
        // Instead of calling order.remove, we can use the 
        // "remove" method of the iterator. This is safe.
        iterator.remove();
    }
}

对于评分标准(B 部分):

  • this.orders+1/2 用于访问(虽然隐含地,with boxes)的元素
  • +1/2 用于将cookieVar( cookieType) 与结果进行比较getVariety()
  • +1 用于比较所有元素,没有越界潜力
  • 删除没有积分(接下来的三个标准,值得两分),因为它会抛出异常
  • +1/2 用于声明和初始化totalRemoved
  • +1/2 为getNumBoxes
  • +1/2 用于正确累积总数+=(尽管他们可能选择不给你这一点ConcurrentModificationException,但根据我的经验,他们只对错误进行一次惩罚)
  • +1/2 正确返回

总分:这部分4/6

请记住,该分数仅适用于该部分;推断,您的问题得分可能是 6/9,这已经高于平均分 (5.46)。还要记住,这些不是线性分级的;即,答对 50% 的问题是相当不错的。

祝你考试顺利!

于 2013-05-07T01:06:07.973 回答
1

此外,当您删除 - 您不应该在该迭代中推进循环索引。如果您的要求是删除多个匹配项,则需要处理该问题。

两种形式的循环都会有问题;第三种形式没有。

  1. for(a : b)将遭受 ConcurrentModificationException,并且循环索引将被错误地推进;
  2. for (int i = 0; i < size; i++)or (在相反方向)i--不会出现异常,但是当您移除项目时元素会移动;i++除非您进行补偿,否则将错误地推进循环索引;
  3. Iterator<CookieOrder>有一个remove()方法,它既能正确补偿循环索引,又不会遭受 ConcurrentModificationException。

例子:

Iterator<CookieOrder> it = orders.iterator();
while (it.hasNext()) {
    CookieOrder cand = it.next();    // 'candidate' for consideration/ removal
    if (cand.getVariety. equals( type)) {
        // Remove;  iterator.remove() handles the loop index correctly.
        boxesRemoved += cand.getNumBoxes();
        it.remove();
    }
}
于 2013-05-07T01:07:28.167 回答