2013-01-17 46 views
-1

我想檢查所有其他值的ArrayList中的所有值,刪除一個,如果他們太接近的價值。這裏有一個例子:迭代ArrayList並檢查所有其他元素

// make an ArrayList of random numbers 
ArrayList<Integer> nums = new ArrayList<Integer>(); 
for (int i=0; i<25; i++) { 
    int rand = int(random(255)); 
    nums.add(rand); 
    println(rand); 
} 

// go through all numbers and compare 
// (loop backwards to prevent ConcurrentModificationException) 
for (int i = nums.size()-1; i >= 0; i--) { 
    int current = nums.get(i); 
    println("Current #: " + current); 

    // how to do this? 
    // not sure if there's a faster way that 
    // would avoid running through the entire 
    // ArrayList for every element... 
    for (Integer other : nums) { 
    if (abs(current - other) < 5) { 
     nums.remove(current); 
    } 
    } 
} 

尋找最乾淨和最有效的方式來做到這一點。

[編輯爲清晰起見]

+2

有什麼理由不與當前解決方案的工作?我看到的唯一選項是首先對ArrayList進行排序。 – RoflcoptrException

+7

爲什麼你要捕捉'Exception',什麼讓你覺得它總是因爲物品是一樣的? (提示:看看例外情況 - 您可能會感到驚訝......) –

+0

結果爲何「不滿意」?發生了什麼,你不喜歡? –

回答

3

你最好做一個不同的方式,以避免併發修改和/或出界異常。

在迭代它時從集合中刪除任何東西是一個冒險的想法(imho),將其替換爲向另一個集合添加內容會更安全。

因此,用等價物替換代碼,但將對象添加到新集合中。

集合是輕量級對象,因此創建它們並不需要太多資源。

最後將原始集合變量分配給新集合。

事情是這樣的:

 final ArrayList<Integer> nums = new ArrayList<Integer>(); 
     final ArrayList<Integer> result = new ArrayList<Integer>(); 
     for (int i = 0; i < 25; i++) { 
      final int rand = Double.valueOf(Math.random() * 255).intValue(); 
      nums.add(rand); 
     } 
     System.out.println(nums); 
     outer: for (Integer current : nums) { 
      // result collection is reevaluated here 
      // and is not modified inside the inner for loop 
      // so, accessing it is safe 
      for (Integer other : result) { 
       if (Math.abs(current - other) < 5) { 
        // there is a too close value, do not put, skip the check 
        continue outer; 
       } 
      } 
      // a too close value doesn't exist - add object 
      result.add(current); 
     } 
     // here you may assing new collection to the old reference, uncomment next line 
     // nums = results; 
+0

感謝亞歷克斯 - 對我來說,至少這個版本有很大的意義。你的意思是,即使使用Iterator(或者像我的例子那樣只是一個for循環)迭代也可能會出現問題?另外:使用迭代器在嵌套for循環示例上節省內存嗎?我將在像素陣列上使用這個非常大的圖像,所以我試圖提前計劃! – JeffThompson

+0

如果你使用迭代器或只是一個for循環,就不會有太大的區別。我認爲我的例子中的語法只是一個簡短的形式,但在內部它也使用迭代器。迭代器是輕量級對象,使用/不使用它們不會影響內存。 –

+1

關於刪除對象 - 有可能您根本不注意並從您迭代的集合中刪除一個元素(帶或不帶迭代器),從而發生異常。迭代器沒有什麼魔力,它只是一個遍歷集合的方便形式。您可以簡單地使用一些int i作爲計數器,並通過調用get(i)方法來獲取循環中集合的元素。效果將是相同的。 –

0

你得到(和隱藏)很多java.util.ConcurrentModificationExceptionjava.lang.IndexOutOfBoundsException,因爲你是從數組中移除,並在同一時間你迭代它。

爲了避免這種情況,你需要使用一個迭代器:

final ArrayList<Integer> nums = new ArrayList<Integer>(); 
    for (int i = 0; i < 25; i++) { 
     final int rand = Double.valueOf(Math.random() * 255).intValue(); 
     nums.add(rand); 
    } 
    System.out.println(nums); 

    for (int i = nums.size() - 1; i >= 0; i--) { 
     final int current = nums.get(i); 
     // println(current); 
     try { 
      for (final Iterator<Integer> iterator = nums.iterator(); iterator.hasNext();) { 
       final Integer other = iterator.next(); 
       if (Math.abs(current - other) < 5) { 
        iterator.remove(); 
        i--; 
       } 
      } 
     } catch (final Exception cme) { 
      System.out.println(cme); 
     } 
    } 

    System.out.println(nums); 
+0

謝謝 - 我有一個Iterator的另一個版本,但對語法不太熟悉,並且遇到了很多錯誤。 – JeffThompson

相關問題