带有 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)
}
}
我对 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())
下面的循环使用相反的顺序通过删除循环中的条目来不影响索引。 (删除索引 j 仅影响位置大于 j 的元素)。
for (int i=keyList.length-1; i>=0;i--){
Ticket t = keyList[i];
if(c.contains(t)){
points+=list.remove(t)
}
}