此代码会输出相同的结果吗?

时间:2013-05-07 00:56:21

标签: java loops

我正在审查AP计算机科学A考试,我写的代码与答案略有不同。你认为你可以检查每个输出是否相同?

  

目标:从CookieOrder ArrayList订单中删除特定类型的Cookie订单,并返回已删除的框数。   请假设所有方法都按照建议工作。

答案:

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();
 }
     

返回框已删除;    }

我放的是什么:

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;
}

这还能用吗?或者,如果你想给我评分,这里是scoring rubric(问题1,B部分)。我很感激帮助;测试是明天,我非常紧张。

3 个答案:

答案 0 :(得分:3)

  

这还能用吗?

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

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

避免CME问题的另一种方法是使用显式迭代器,并使用Iterator.remove()方法进行删除。 (这适用于ArrayListLinkedList,但某些更具异国情调的列表类型可能会因某种原因返回不支持Iterator的{​​{1}}。)

答案 1 :(得分:2)

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

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

首先从ArrayList的{​​{1}}方法获取迭代器。与iterator一样,ArrayList 泛型 - 也就是说,它是Iterator,而不仅仅是Iterator<CookieOrder>

Iterator

Iterator<CookieOrder> iterator = order.iterator(); 类有两个关键方法:IteratorhasNext。您想检查每个项目,直到没有项目为止。每当你调用next时,都会将迭代器推进一个。你的代码看起来像这样:

next

特别针对您的问题:

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

    // do something with o
}

对于得分规则(B部分):

  • +1/2用于访问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(); } } 的元素(虽然隐含地,使用this.orders
  • +1/2,用于将boxescookieVar)与cookieType的结果进行比较
  • +1用于比较所有元素,没有超出界限
  • 没有删除要点(接下来的三个标准,值得两分),因为它会抛出异常
  • +1/2用于声明和初始化getVariety()
  • +1 totalRemoved
  • +1/2正确累计getNumBoxes的总数(尽管他们可能会选择不为+=提供这一点,但根据我的经验,他们只会对错误进行一次处罚)< / LI>
  • +1/2正确返回

此部分的总分: 4/6

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

祝你的考试好运!

答案 2 :(得分:1)

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

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

  1. for(a : b)将遭受ConcurrentModificationException,并且循环索引将无法正确推进;
  2. for (int i = 0; i < size; i++)或(反方向)i--不会遭遇异常,但删除项目时元素会移动;除非您补偿,否则i++会错误地推进循环索引;
  3. Iterator<CookieOrder>有一个remove()方法,它可以正确地补偿循环索引。不会遭受ConcurrentModificationException。
  4. 示例:

    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();
        }
    }