2015-01-15 32 views
1

我有一個列表,我正在循環它刪除列表中的項目,如果有匹配。 如果列表中的項目被刪除,我正在使用i = -1。但它從頭再次循環。有一個更好的方法嗎?更好的方式來遍歷列表<String>並刪除項目

private List<String> populateList(List<String> listVar) { 
    List<String> list = new ArrayList<String>(); 
    list.add("2015-01-13 09:30:00"); 
    list.add("2015-01-13 06:22:12"); 
    list.add("2015-01-12 05:45:10"); 
    list.add("2015-01-12 01:52:40"); 
    list.add("2015-01-12 02:23:45"); 
    return list; 
} 

private void removeItems() { 
    List<String> list = new ArrayList<String>(); 
    list = populateList(list); 
    System.out.println("List before modification : "+list); 
    for (int i = 0; i < list.size(); i++) { 
     String dateNoTime = list.get(i).split(" ")[0]; 
     System.out.println(" Going over : "+list.get(i)); 
     if(!dateNoTime.equalsIgnoreCase("2015-01-13")) { 
      System.out.println("  Removing : "+list.get(i)); 
      list.remove(i); 
      i = -1; //This is making the loop start from scratch. Is there a better way? 
     } 
    } 
    System.out.println("List after modification: "+list+"\n\n"); 
} 
+0

我錯過了什麼?爲什麼你不能刪除部件'我= -1'? – SOfanatic 2015-01-15 17:56:22

+0

應該是併發修改異常!改用Iterator。 – 2015-01-15 17:57:01

+0

只是反向循環。 (從結尾到開始) – njzk2 2015-01-15 17:57:20

回答

5

Java的List<T>提供使用ListIterator<T>去除它的項目有更好的方式:

ListIterator<String> iter = list.listIterator(); 
while (iter.hasNext()) { 
    String s = iter.next(); 
    String dateNoTime = s.split(" ")[0]; 
    if(!dateNoTime.equalsIgnoreCase("2015-01-13")) { 
     iter.remove(); 
    } 
} 
0

使用迭代器。

Javadoc中迭代說以下

迭代器允許調用者具有良好定義的語義迭代期間移除底層集合的元素。

1

您可以使用具有去除方法Iterator接口。

Iterator<String> iterator = list.iterator(); 
    while (iterator.hasNext()) 
    { 
     String next = iterator.next(); 
     String dateNoTime = next.split(" ")[0]; 

     if(!dateNoTime.equalsIgnoreCase("2015-01-13")) { 
      System.out.println("  Removing : "+next); 
      iterator.remove(); 
     } 
    } 
0

或者您可以使用番石榴API來實現它。

FluentIterable 
     .from(list) 
     .transform(new Function<String, String>(){ 
      @Override 
      public void apply(String input){ 
       return input.split(" ")[0]; 
      } 
     }).filter(new Predicate<String>(){ 
      @Override 
      public boolean apply(String input){ 
       return input.equalsIgnoreCase("2015-01-13"); 
      } 
     }).toList(); 
1

具有Java-8,就可以簡化整個事情:

List<String> filtered = list.stream().filter(item -> item.split(" ")[0] 
                 .equalsIgnoreCase("2015-01-13")) 
                 .collect(Collectors.toList()); 

我覺得這是一個接一個檢查他們從列表中刪除項目的最短途徑。 (就代碼大小而言,我的意思是'最短',而不是複雜性)。

1

當您使用索引遍歷列表並且要從列表中刪除項目時,需要注意處理索引的方式。 (通過迭代做好remove在@ dasblinkenlight的答案是在這種情況下更好,但有些情況下這是不可能的其它類似情況)

假設你只是刪除了復位i行:

for (int i = 0; i < list.size(); i++) { 
    String dateNoTime = list.get(i).split(" ")[0]; 
    System.out.println(" Going over : "+list.get(i)); 
    if(!dateNoTime.equalsIgnoreCase("2015-01-13")) { 
     System.out.println("  Removing : "+list.get(i)); 
     list.remove(i); 
     //i = -1; //This is making the loop start from scratch. Is there a better way? 
    } 
} 

現在,當i==2,你決定你需要刪除元素。當你這樣做時,元素3的項目就變成元素2,而元素4的元素變成元素3,依此類推。

但是然後你回到頂部並增加i。現在是3.結果是元素3,但現在是元素2的元素,根本不會被檢查。它被跳過。

有幾種方法可以解決這個問題。

一個是確保i不增加。我已經看到了好的程序員做這樣的事情:

for (int i = 0; i < list.size(); i++) { 
    String dateNoTime = list.get(i).split(" ")[0]; 
    System.out.println(" Going over : "+list.get(i)); 
    if(!dateNoTime.equalsIgnoreCase("2015-01-13")) { 
     System.out.println("  Removing : "+list.get(i)); 
     list.remove(i); 
     i--; // Move "i" backwards so that no elements are skipped 
    } 
} 

就個人而言,我不喜歡修改for循環像這裏面的指數,所以我會用

int i = 0; 
while (i < list.size()) { 
    String dateNoTime = list.get(i).split(" ")[0]; 
    System.out.println(" Going over : "+list.get(i)); 
    if(!dateNoTime.equalsIgnoreCase("2015-01-13")) { 
     System.out.println("  Removing : "+list.get(i)); 
     list.remove(i); 
    } else { 
     i++; 
    } 
} 

[注意,在快樂在這兩種情況下,在終止條件中使用list.size()都很重要,並且不要將原始值保存在變量中。該列表的大小會發生變化,並且要使用新的大小終止確認時]

另一種解決方案,在某些情況下是合適的是在列表中向下走:

for (int i = list.size() - 1; i >= 0; i--) 
    String dateNoTime = list.get(i).split(" ")[0]; 
    System.out.println(" Going over : "+list.get(i)); 
    if(!dateNoTime.equalsIgnoreCase("2015-01-13")) { 
     System.out.println("  Removing : "+list.get(i)); 
     list.remove(i); 
    } 
} 

其沒有按元素轉移時沒有問題。

+0

不錯。非常好的解釋!謝謝! – 2015-01-15 18:27:11

相關問題