我遇到这种情况:如果我在HashSet中找到一个特定值,我必须更新一个字段,清除该集并返回该字段。 这里有一个例子:
static Set<Integer> testSet = new HashSet<>();
static Integer myField = null; // the field could be already != null
public static int testClearSet()
{
for (int i = 0; i < 100; i++) { // this is just for the test
testSet.add(i);
}
for (Integer n : testSet) {
if (n == 50) {
myField = n;
testSet.clear();
return myField;
}
}
return -1;
}
我想知道如果这样做是安全的,考虑到后来我应该重用该集合的事实。
我问这个,因为我知道在迭代时对Collection进行更改不是一个“好习惯”,但我认为这种情况有点不同。
可能的解决方案是:
boolean clear = false;
for (Integer n : testSet) {
if (n == 50) {
myField = n;
clear = true;
break;
}
}
if (clear) {
testSet.clear();
return myField;
}
那么,哪一个是正确的方式?
答案 0 :(得分:1)
使用显式迭代器时,从集合中删除元素应该是安全的。因此以下应该是安全的:
Iterator<Integer> iterator = testSet.iterator();
while (iterator.hasNext()) {
Integer element = iterator.next();
if (element.intValue() == 50) {
testSet.clear();
break;
}
}
答案 1 :(得分:0)
如果您知道Set
仅在一个帖子中进行更改,那么您可以像第一个示例中那样进行清理。
方法clear()
不会抛出ConcurrentModificationException
。
答案 2 :(得分:0)
如果在手动更改后继续迭代,则仅抛出#bad
。
你所做的就是改变它并中止迭代,所以它应该100%安全(无论for-each实现如何)。
真正的问题是,代码的可读性。理想情况下,一段代码应该完成一项工作,如果这项工作很复杂,请将其拆分。特别是,您的代码包含两个部分:条件和操作:
Public Sub exportCSV()
MyRes.MoveFirst
strCsvFile = "D:\Mycsv.csv"
fHndl = FreeFile
Open strCsvFile For Output As fHndl
out2 = MyRes.GetFieldNameAt(1)
Print #fHndl, out2
MyRes.MoveFirst
While Not MyRes.IsEOF
out = MyRes.GetField("ID")
' Debug.Print out2
Print #fHndl, out
MyRes.MoveNext
Wend
MsgBox ("Downloaded")
Close #fHndl
End Sub
所以:
ConcurrentModificationException
后一种方法可以用单个API调用替换,供您查明。
答案 3 :(得分:0)
您的代码都可以使用。
使用fail fast迭代器进行迭代时,修改集合确实存在限制。这意味着,如果在创建迭代器后集合中有任何修改,则使用fail fast迭代器进行迭代将失败。 java集合类返回的所有默认迭代器都是失败快速迭代器。
private void removeDataTest (Collection<String> c, String item) {
Iterator<String> iter = c.iterator(); //Iterator is created.
while (iter.hasNext()) {
String data = iter.next();
if (data.equals(item)) {
//c.remove(data); //Problem. Directly modifying collection after this iterator is created. In the next iteration it will throw concurrent modification exception.
iter.remove(); //This is fine. Modify collection through iterator.
//c.clear(); break; //This is also should be okay. Modifying the collection directly, but after that it is breaking out and not using the iterator.
}
}
}
在您的代码中,您不会在修改集后继续迭代。所以应该没问题。