2013-04-05 59 views
12

昨天,當我回答質疑getting ConcurrentModificationException error while using iterator and remove我添加了一個通知,我們是否需要在ArrayList上使用迭代器?

這不是一個好主意,當你的ArrayList使用迭代器。

你不需要深刻理解那個問題就可以回答那個問題。

在那裏,我有兩個意見,我錯了。

我的論點:

  1. 的代碼是迭代器可讀的要少得多。

  2. 有可能引發難以調試的ConcurrentModificationException。

你能解釋一下嗎?

問題: 我們是否曾經需要在ArrayList上使用迭代器?

UPD

這是一個關於明確使用迭代器。

+2

取決於「使用迭代器」的含義。每次你爲'(Integer x:listOfInts)'做的時候,你都隱式地使用了一個迭代器。 – 2013-04-05 06:59:56

+0

@Oli查爾斯沃思,感謝您指出這一點!是的,我的意思是明確的迭代器。 – Vitaly 2013-04-05 07:38:16

回答

19

使用ArrayLists的迭代器的一個大用例是當您想要在迭代時刪除元素。你只有三個安全解決方案:

  • 使用你想要保留在另一個列表
  • 叢林與指標

假設你沒有一個迭代器及其remove方法

  • 複製的元素在迭代過程中,使用迭代器是一個意思是避免ConcurrentModificationException

    可讀性參數是主觀的。就我個人而言,我沒有發現一個乾淨地聲明的迭代器不易讀。這並不重要,因爲迭代器是同時迭代和刪除的安全方法。

  • +1

    我唯一的好看的原因是:「使用迭代器及其移除方法」。如果有人只是想迭代並從列表中刪除不需要的項目。謝謝。 – Vitaly 2013-04-09 23:33:37

    +0

    @dystroy抱歉打開了這個,但我不明白爲什麼你需要使用迭代器從ArrayList中移除一個元素? – 12rad 2013-07-30 21:19:21

    +0

    @Vitaly我做了一個快速測試\t列表 a = new ArrayList (); \t \t \t a.add(「a」); \t \t \t a.add(「b」); \t \t \t a.add(「c」); \t \t \t a.add(「d」); \t \t \t a.add(「e」); \t \t \t a.remove(「b」);它似乎工作。 – 12rad 2013-07-30 21:19:51

    2

    是的,我們需要。 ArrayList只是List接口的一個實現,所以經常你的代碼會處理一個列表,甚至不知道它是一個ArrayList。此外,新的for-loop語法在內部使用迭代器。

    +0

    謝謝。是關於ArrayList的。 – Vitaly 2013-04-05 07:42:44

    0

    您可能正在討論顯式使用迭代器(因爲:操作符也在幕後使用迭代器)。

    假設你想要兩個「指針」遍歷數組,但速度取決於實際的元素值。 你如何做到這一點,而不明確使用迭代器(當然沒有elementAt)。

    例如(僞碼):

    element1 = first element; 
    element2 = first element; 
    while(element1.hasNext && element2.hasNext) 
    { 
        if(element1 * 2 < element) 
        { 
         element2 = element2.next; 
        } 
        else 
        { 
         element1 = element1.next; 
        } 
    
        //do something with the pair of elements 
    } 
    
    +0

    謝謝。我們可以使用ArrayList.elementAt(),爲什麼不能?:)你能說清楚你的意思是「速度取決於實際的元素值」嗎? – Vitaly 2013-04-05 07:47:05

    +0

    @Vitaly因爲那麼你的代碼是'ArrayList ' - 特定的,而不是一般的任何'List.' – EJP 2013-04-05 11:40:20

    +0

    它不是「我的代碼」:)而問題是關於如果我們知道它是ArrayList。 – Vitaly 2013-04-05 13:10:59

    -1

    該代碼是與迭代器可讀少得多。

    這完全是你的看法,我不分享它。

    有可能引發難以調試的ConcurrentModificationException。

    無論您是否使用迭代器,這都可能存在。這個異常告訴你一些關於你的代碼的有用信息,你可能完全錯過了,這更難調試。

    個人而言,我更喜歡能夠在ArrayList和LinkedList之間準確編寫代碼,並讓編譯器或API實現細節。

    道德是你不應該按照既定的事實去掉你自己的無支持的觀點。

    7

    沒有一個答案似乎adresres迭代器的原因。迭代器設計模式的創建是因爲對象應該控制自己的狀態(除了可能只有公有屬性的值對象)。

    可以說我們有一個包含數組的對象,並且在該對象中有一個接口來將項添加到該數組。但是,你必須做這樣的事情:

    class MyClass 
    { 
        private ArrayList<Item> myList; 
    
        public MyClass() 
        { 
         myList = new ArrayList(); 
        } 
    
        public addItem(Item item) 
        { 
         item.doSomething(); // Lets say that this is very important before adding the item to the array. 
         myList.add(item); 
        } 
    } 
    

    現在,如果我在上面的類有這個方法:

    public ArrayList getList() 
    { 
        return myList; 
    } 
    

    有人能拿參考通過這種方法MYLIST和項目添加到陣列中, without calling item.doSomething();這就是爲什麼你不應該返回數組的引用,而是返回它的迭代器。可以從數組中獲取任何項目,但無法操作原始數組。所以MyClass對象仍然控制着它自己的狀態。

    這是迭代器發明的真正原因。

    相關問題