带有 for 循环和 return 语句的 Junit 测试问题

Junit Testing issue with for loop and return statement

我对 for 循环和 return 语句有点困惑。我希望有人能给我解释一下这是怎么回事。

    private Map<Ticket, Integer> list;

public RessourceBasedAccessControl32603() {
    super();
    list = new HashMap<>();
}

我必须为此 junit 测试编写一个工作方法:

@Test
void testRemoveCollection2() {
    accessControl.add(t1, 10);
    accessControl.add(t2, 20);
    accessControl.add(t3, 30);
    Set<Ticket> s = new HashSet<>();
    s.add(t1);
    s.add(t3);
    int actual = accessControl.remove(s);
    assertEquals(40, actual);
}

如果我编写这段代码,我会得到预期的 40。

    @Override
public int remove(Collection<Ticket> c) { 
    int points = 0;
    for (Ticket i : c) {
        if (list.containsKey(i)) {
            points += list.remove(i);
        }
    }
    return points;
}

如果我写这段代码,我会得到 30 而不是 40。我只是得到最后一次添加的数字 (t3) 而不是 t1 + t3)。我很确定它不会因为第一个 return 而总结,但如果我删除第一个 return,我会得到一个“java.util.ConcurrentModificationException”。为什么我不能像上面的例子那样只使用一个return?有什么不同?请问还有办法得到HashSet中所有tickets的求和方法吗?

    @Override
public int remove(Collection<Ticket> c) {
    int points = 0;
    for (Ticket i : list.keySet()) {
        if (c.contains(i)) {
            points += list.remove(i);
            return points;
        }
    }
    return points;
}

非常感谢!

ConcurrentModificationException 发生了,因为您从 HashMap 中删除了一个项目,同时仍在对其进行迭代。如果您保留 return,那么您在修改它时不会迭代密钥集。

如果您想走那条路,请在完成迭代后删除项目。

public int remove(Collection<Ticket> c) {
    int points = 0;
    for (Ticket i : list.keySet()) {
        if (c.contains(i)) {
            points += list.get(i);
            // return points;
        }
    }
    list.keySet().removeAll(c);
    return points;
}

在Java中,您不能在for循环中使用这种语句格式对集合进行操作。 for (Ticket i : list.keySet()) - 在内部它使用集合中的迭代器并在迭代期间修改它会破坏顺序,因此出现异常。

您可以使用两种方法:

第一个就是先加点然后做list.removeAll(Collection<?>...)

第二个可以在将 keySet 转换为像 new ArrayList<>(list.keySet())

这样的实际列表后使用带有索引的旧 for 语句来完成

下面的循环使用相反的顺序通过删除循环中的条目来不影响索引。 (删除索引 j 仅影响位置大于 j 的元素)。

for (int i=keyList.length-1; i>=0;i--){
   Ticket t = keyList[i];
   if(c.contains(t)){
      points+=list.remove(t)
   }
}