此操作是否安全?如果不是,爲了做同樣的事情,如何編寫代碼?此操作是否安全?
Set<Object> set;
......
for (Object o: set) {
if (some_condition) {
set.remove(o);
}
}
此操作是否安全?如果不是,爲了做同樣的事情,如何編寫代碼?此操作是否安全?
Set<Object> set;
......
for (Object o: set) {
if (some_condition) {
set.remove(o);
}
}
不,它不是 - 因爲您不允許修改您正在迭代的集合,而不是通過迭代器。有很多方法可以解決這個問題。這裏有一個:
for (Iterator<Object> iterator = set.iterator(); iterator.hasNext();)
{
Object value = iterator.next();
if (someCondition)
{
iterator.remove();
}
}
另一種選擇是建立項目的獨立的列表中刪除,然後將它們全部刪除後你遍歷集合:
List<Object> itemsToRemove = new ArrayList<Object>();
for (Object x in set)
{
if (someCondition)
{
itemsToRemove.add(x);
}
}
set.removeAll(itemsToRemove);
現在,它會拋出ConcurrentModificationException
。
的for()
循環使用的Iterator
內部,保持一個編輯計數和如果編輯計數不匹配的後盾Set
的編輯數量,它拋出一個ConcurrentModificationException
當然,這取決於實際執行收集,但這是記錄的行爲,例如在the HashSet
docs:
此類的 iterator方法返回的迭代器是快速失敗的:如果 組隨時修改後的 迭代器是通過迭代器自身的移除 創建的,以任何方式,除了 方法,
Iterator
將拋出一個ConcurrentModificationException
。因此, 併發 修改的,迭代器很快就會完全失敗 ,而不是 在 未來不確定的時間冒着任意的,非確定性 行爲。
否 - 您的條件首次通過時,您會在下一次迭代中獲得ConcurrentModificationException
。
在一般情況下,它是不是安全的直接修改集合在遍歷它,和迭代器是在這種情況下,「快速失敗」(因爲整體上,而他們可以檢測到的變化,有沒有通用方式弄清楚如何應對他們)。
在這種情況下,一個工作的習慣用法是使用迭代器自己的remove()
方法。刪除元素在這個可控的方式不斷迭代知道發生了什麼,並有碰巧迭代順序什麼一致的語義,所以可以作爲你所期望的:
Iterator<Object> iter = set.iterator();
while (iter.hasNext()) {
final Object o = iter.next();
if (some_condition) {
iter.remove();
}
}
然而要注意remove()
是「可選操作」,並非所有集合的迭代器都支持它。如果你堅持在這種情況下,這將始終工作是採取集的副本替代,遍歷是從原集刪除的對象,像這樣:
Set<Object> copy = new HashSet<Object>(set);
for (Object o: copy) {
if (some_condition) {
set.remove(o);
}
}
因爲迭代超過copy
,而修改發生在set
,所以沒有發生併發修改,並且迭代器很滿意。
這就是「總是工作「,只要設置支持刪除一般,當然:) – 2011-02-01 17:31:09
很好的解釋! – peakit 2011-02-01 17:37:35
Set<Object> set;
......
Set<Object> objectsToBeDeleted = new HashSet<Object>();
for (Object o : set) {
if (some_condition) {
objectsToBeDeleted.add(o);
}
}
for (Object o : objectsToBeDeleted) {
set.remove(o);
}
第一句:*因爲你不是很多*? – 2011-02-01 17:33:59