是否安全清除如果找到正确的值,则在循环中设置?

时间:2016-08-12 10:26:06

标签: java loops set clear

我遇到这种情况:如果我在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;
}

那么,哪一个是正确的方式?

4 个答案:

答案 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.
         }
    }
}

在您的代码中,您不会在修改集后继续迭代。所以应该没问题。