讓程序向衛(wèi)星發(fā)射一樣受控:謹(jǐn)慎在for循環(huán)中的使用集合的remove(int index)
Posted on 2010-10-01 18:59 瘋狂 閱讀(2691) 評(píng)論(5) 編輯 收藏 所屬分類: java 、方法論 考慮以下代碼:此問題以前在javaeye上看見過,不過在我們的代碼評(píng)審的時(shí)候仍然發(fā)現(xiàn)相同問題,代碼看著很正常,但結(jié)果卻差之千里。
目的:刪除list里面的所有元素。
List list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
list.add("6");
for (int i = 0; i < list.size(); i++) {
list.remove(i);
}
for (int i = 0; i < list.size(); i++) {
結(jié)果:
2
4
6
為什么沒刪除完,分析一下:
當(dāng)在刪除的過程中,i 在變大,但是list中的元素的位置則在變小,例如:
當(dāng)刪掉第一個(gè)元素的時(shí)候,第二個(gè)元素的index立馬變成o,而這時(shí)候i卻成了1 這就導(dǎo)致index為0的元素?zé)o法刪除。
這種情況問題很難發(fā)現(xiàn)。
但有的人喜歡這樣寫,到是能及時(shí)發(fā)現(xiàn)問題:
int n = list.size();
for (int i = 0; i < n; i++) {
list.remove(i);
}
這個(gè)時(shí)候就會(huì)拋出 java.lang.IndexOutOfBoundsException異常,原因很明顯,list的size是在每次刪除的時(shí)候都減1,而n卻一直沒變,最終導(dǎo)致越界。
當(dāng)然有的人提出改進(jìn)的方法:
for (int i = list.size() - 1; i >= 0; i--) {
當(dāng)刪除list中index最大的元素后,原來倒數(shù)第二個(gè)元素變?yōu)樽畲螅莍ndex變?yōu)樵瓉淼膕ize-1,通過i也變成size-1。最終原來index為0 的元素變?yōu)閕ndex最大的元素。
個(gè)人總結(jié)出的原則:1 盡量不要讓單個(gè)for循環(huán)中的兩個(gè)邊界發(fā)生變化,這樣我們可以對(duì)游標(biāo)(i)的變化心里有數(shù)。
2 不要把游標(biāo)(i)和不斷變化的資源位置掛鉤,這樣我們可以對(duì)資源的變化心里有數(shù)。
關(guān)于list的刪除方法就不在這將了,不管用iterator,還是其他的
總的來說,讓程序按照我們的設(shè)計(jì)步驟進(jìn)行才是成功的。就像這幾天的嫦娥2號(hào),要是發(fā)生這樣的事情,就慘了,本來要先點(diǎn)一級(jí)火箭,再二級(jí),再三級(jí),結(jié)果一級(jí)點(diǎn)了,就直接3級(jí)了,估計(jì)也沒法繞月了,這是多么大的損失啊。
目的:刪除list里面的所有元素。
List list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
list.add("6");
for (int i = 0; i < list.size(); i++) {
list.remove(i);
}
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
結(jié)果:
2
4
6
為什么沒刪除完,分析一下:
當(dāng)在刪除的過程中,i 在變大,但是list中的元素的位置則在變小,例如:
當(dāng)刪掉第一個(gè)元素的時(shí)候,第二個(gè)元素的index立馬變成o,而這時(shí)候i卻成了1 這就導(dǎo)致index為0的元素?zé)o法刪除。
這種情況問題很難發(fā)現(xiàn)。
但有的人喜歡這樣寫,到是能及時(shí)發(fā)現(xiàn)問題:
int n = list.size();
for (int i = 0; i < n; i++) {
list.remove(i);
}
這個(gè)時(shí)候就會(huì)拋出 java.lang.IndexOutOfBoundsException異常,原因很明顯,list的size是在每次刪除的時(shí)候都減1,而n卻一直沒變,最終導(dǎo)致越界。
當(dāng)然有的人提出改進(jìn)的方法:
for (int i = list.size() - 1; i >= 0; i--) {
list.remove(i);
}
這樣確實(shí)能全部刪除,但是存在僥幸。因?yàn)楹臀覀儗?shí)際的想法有悖的,我們的想法是從大到小刪除,但是實(shí)際上發(fā)生的事情確實(shí)我們總是在刪除最大的。分析一下:當(dāng)刪除list中index最大的元素后,原來倒數(shù)第二個(gè)元素變?yōu)樽畲螅莍ndex變?yōu)樵瓉淼膕ize-1,通過i也變成size-1。最終原來index為0 的元素變?yōu)閕ndex最大的元素。
個(gè)人總結(jié)出的原則:1 盡量不要讓單個(gè)for循環(huán)中的兩個(gè)邊界發(fā)生變化,這樣我們可以對(duì)游標(biāo)(i)的變化心里有數(shù)。
2 不要把游標(biāo)(i)和不斷變化的資源位置掛鉤,這樣我們可以對(duì)資源的變化心里有數(shù)。
關(guān)于list的刪除方法就不在這將了,不管用iterator,還是其他的
總的來說,讓程序按照我們的設(shè)計(jì)步驟進(jìn)行才是成功的。就像這幾天的嫦娥2號(hào),要是發(fā)生這樣的事情,就慘了,本來要先點(diǎn)一級(jí)火箭,再二級(jí),再三級(jí),結(jié)果一級(jí)點(diǎn)了,就直接3級(jí)了,估計(jì)也沒法繞月了,這是多么大的損失啊。