對List遍歷過程當中添加和刪除的思考

對List遍歷過程當中添加和刪除的思考java

平時開發過程當中,很多開發者都遇到過一個問題:在遍歷集合的的過程當中,進行add或者remove操做的時候,會出現2類錯誤,包括:
java.util.ConcurrentModificationException for in遍歷過程當中add/remove致使的錯誤
java.lang.IndexOutOfBoundsException 越界錯誤,for循環的時候刪除元素。
最佳實踐併發

add操做:利用原生的for循環。remove操做利用foreach操做。以下所示:
//OK,利用 iterator 和 其remove 方法
@Test
public void testIteratorRemove2() {
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
if ("3".equals(iterator.next())) {
iterator.remove();
}
}
System.out.println(list);
}指針

//OK 利用for循環。
@Test
public void testForAdd() {
for (int i = 0, length = list.size(); i < length; i++) {
if (list.get(i).equals("2")) {
list.add("2");
}
}
}
經典錯誤1對象

以下代碼本意是:經過iterator的方式從頭至尾變遍歷list中的元素。
@Test
public void testIteratorRemove2() {
while (list.iterator().hasNext()) {
System.out.println(list.iterator().next());
}
}
可是該段代碼永遠都會輸出 list的第一元素,爲何?關鍵錯誤在鏈式寫法上:
while (list.iterator().hasNext()) {}
每次循環時候先調用了list.iterator() 在該方法中每次都是從新new了一個新的對象
public Iterator<E> iterator() {
return new Itr();
}
因此每一次都是一個新的遍歷對象,因此輸出第一個元素。
那麼爲何每次都要new一個新的Itr()?我猜測應該是爲了併發的讀,每次讀的都是一份獨立的數據,避免多個併發讀的時候,出現當前指針問題。
處理辦法:將list.iteraotr() 放在外面便可,保證循環中循環的是1個對象。
@Test
public void testIteratorRemove2() {
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
if ("3".equals(iterator.next())) {
iterator.remove();
}
}
System.out.println(list);
}
經典錯誤2開發

// 死循環
@Test
public void testForAdd2() {
for (int i = 0; i < list.size(); i++) {
if (list.get(i).equals("3")) {
list.add("3");
}
}
}
當if條件知足的時候,該方法永遠不會結束,爲何?
對於for循環 for (int i = 0; i < list.size(); i++)有3個部分,第一個部分爲初始化,只執行一次。第二個部分每次都會執行,第三個部分也是每次都會執行。
上述問題的第二步會致使無限循環:由於for中每一次循環都會在list添加了一個元素,每次步進爲1,內部元素也是每次都加1.
如何處理該問題: list.size()放在第一部分,第一部分只初始化一次。
//OK 利用for循環。
@Test
public void testForAdd() {
for (int i = 0, length = list.size(); i < length; i++) {
if (list.get(i).equals("2")) {
list.add("2");
}
}
}
經典錯誤3rem

//java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
@Test
public void testForRemove() {
for (int i = 0, length = list.size(); i < length; i++) {
if (list.get(i).equals("3")) {
list.remove("3");
}
}
}
該錯誤在list.add("3")的時候就不會發生該錯誤,具體緣由是什麼?
Liu CF:轉載請保留原文連接,3Q!get

相關文章
相關標籤/搜索