面試題:在一個集合中,有幾個隨機字符串,有些含有a,有些沒有a,用普通for循環遍歷,移除含有a字符的字符串,示例如下,請問最終的打印輸出結果是?
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("abc");
list.add("afg");
list.add("amf");
list.add("mfg");
list.add("age");
list.add("ofh");
for (int i= 0; i < list.size();i++){
if(list.get(i).contains("a")){
list.remove(i);
}
}
for (String str : list) {
System.out.println(str);
}
}
實際結果:afg mfg ofh
結果中,竟然有字符串中含有a,它不是應該已經被移除了嗎?爲什麼會這樣呢?
解析:
在list集合遍歷的時候,每一次循環,指針都會向後移動一位(理解爲i從0開始,每次都會後移一位),但是,如果有元素被刪除了,那後面的所有元素都會順次向前移動一位(0索引的元素沒了,那後面的就會補過來啊),所以每次操作結果如下表:
是不是很直觀的可以看出,由於每次刪除元素後,數組下標會自動前移一位,導致存在落網之魚
如何解決這一問題呢?我們根據原理分析,既然每次刪除會造成數組下標前移一位,數據向前,那麼我們可以
1)防止下標前移造成的漏查
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("abc");
list.add("afg");
list.add("amf");
list.add("mfg");
list.add("age");
list.add("ofh");
for (int i= 0; i < list.size();i++){
if(list.get(i).contains("a")){
list.remove(i);
i--; //簡單的一行代碼,即每次刪除元素後,使下標前移一位,避免漏查
}
}
for (String str : list) {
System.out.println(str);
}
}
2)防止數據前移
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("abc");
list.add("afg");
list.add("amf");
list.add("mfg");
list.add("age");
list.add("ofh");
for (int i = list.size() -1; i >=0 ; i--) { //從後往前查,從後面開始刪除,避免數據前移
if(list.get(i).contains("a")){
list.remove(i);
}
}
for (String str : list) {
System.out.println(str);
}
}
記住啦,下次面試還會有喲