我一直在研究这段代码。这是我想要发生的伪代码:
a.check如果部分(列表)大小为0
b。如果部分大小为0,则通过调用sections.add(newSection)
自动将学生注册到该部分
c。如果章节大小不为零,请检查与时间表的冲突
d。如果没有冲突,则通过调用sections.add(newSection)
将学生注册到该部分
e.else什么都不做
Java不断向我抛出“java.util.concurrentmodificationexception”错误。我知道,我不应该在遍历列表时改变ArrayList的大小,因为它会修改迭代器。还有另一种解决方法吗? :d
非常感谢。 非常感谢您的帮助。 :)
public String enrollsTo(Section newSection){
StringBuffer result = new StringBuffer();
String resultNegative = "Failed to enroll in this section.";
String resultPositive = "Successfully enrolled in section: " + newSection.getSectionName() + ".";
int previousSectionSize = sections.size();
if(this.sections.isEmpty()){
this.sections.add(newSection);
result.append(resultPositive);
}else{
for(Iterator<Section> iterator = sections.iterator(); iterator.hasNext() ; ){
Section thisSection = iterator.next();
if(thisSection.conflictsDayWith(newSection)==false &&
thisSection.conflictsTimeWith(newSection)==false){
this.sections.add(newSection); //<-- i believe the problem lies here.
result.append(resultPositive);
}
}
}
// if(this.sections.size() == previousSectionSize){
// result.append(resultNegative);
// }
return result.toString();
}
答案 0 :(得分:1)
不要在for循环中执行sections.add(newSection)
,因为这是对当前正在迭代的集合的修改。
另外,在决定是否添加newSection
之前,您不想检查所有部分吗?也许是这样的:
boolean conflict = false;
for (...) {
if (/* check for conflict */) {
conflict = true;
break;
}
}
if (!conflict) {
sections.add(newSection);
}
答案 1 :(得分:0)
来自ConcurrentModificationException的javadoc(我的重点):
检测到并发的方法可能抛出此异常 在不允许进行此类修改时修改对象。
例如,一个线程通常不允许修改 一个集合,而另一个线程正在迭代它。一般来说, 在这些情况下,迭代的结果是不确定的。 一些迭代器实现(包括所有通用的实现) 由JRE提供的目的集合实现可以选择 如果检测到此行为,则抛出此异常。那个迭代器 这被称为故障快速迭代器,因为它们很快就会失败 干净利落,而不是冒着任意的,非确定性的行为冒险 未来不确定的时间。
请注意,此异常并不总是表示对象具有 由另一个线程同时修改。如果是单线程 发出一系列违反合同的方法调用 一个对象,该对象可能抛出此异常。 例如,如果是 线程在迭代时直接修改集合 使用失败快速迭代器进行集合,迭代器将抛出此异常 异常。强>
请注意,通常情况下无法保证快速失败的行为 说话,在场的情况下不可能做出任何硬性保证 不同步的并发修改。失败快速操作投掷 ConcurrentModificationException是尽力而为的。因此,它 编写一个依赖于此异常的程序是错误的 它的正确性:应该只使用ConcurrentModificationException 检测错误。
潜在的解决方案:不是直接添加到您要重复的列表中,而是添加到临时列表中,然后在您完成迭代后,执行addAll()
。
答案 2 :(得分:0)
迭代收集时,您无法修改它。抛出异常的行this.sections.add(newSection);
。您可能需要使用一些布尔标记来检查条件
if(thisSection.conflictsDayWith(newSection)==false &&
thisSection.conflictsTimeWith(newSection)==false)
如果您的布尔标记为真,则在for循环之后,您可以编写
this.sections.add(newSection);
result.append(resultPositive);
答案 3 :(得分:0)
你的假设是正确的,
this.sections.add(newSection);
绝对是您问题的根源。
最简单的解决方案:有一个表示该部分可用性的布尔值。首先假设它可用。如果迭代器中存在任何冲突,请将其设置为false。在迭代器之后,如果该部分可用,则添加该部分(布尔值为true)。
答案 4 :(得分:0)
当您在迭代其元素时修改集合时,通常会发生ConcurrentModificationExceptions。请阅读this tutorial以获取更多详细信息以及此旧帖子Why does it.next() throw java.util.ConcurrentModificationException?
答案 5 :(得分:0)
我同意@sudocode你不想在每次找到一个不冲突的部分时添加newSection。我会想到,当你在调试器中单步执行代码时,这将是显而易见的。 ;)
BTW另一种(更加模糊的)没有标志的方式
CHECK: {
for (...) {
if (/* check for conflict */)
break CHECK;
}
sections.add(newSection);
}