2013-04-05 58 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对象仍然控制着它自己的状态。

    这是迭代器发明的真正原因。

    相关问题