昨天,当我回答问题getting ConcurrentModificationException error while using iterator and remove时,我添加了一条通知
使用ArrayLists时使用迭代器不是一个好主意。
您无需深入了解该问题即可回答。
在那里,我得到两条评论,我错了。
我的论点:
使用迭代器,代码的可读性要差得多。
有可能引发难以调试的ConcurrentModificationException。
你能解释一下吗?
问题: 我们是否需要在ArrayList上使用迭代器?
UPD
这是关于明确使用Iterator。
答案 0 :(得分:21)
使用ArrayLists的迭代器的一个大用例是当你想在迭代时删除元素。您只有三个安全的解决方案:
remove
方法假设您在迭代时没有add
,使用迭代器是避免 ConcurrentModificationException
的意思。
可读性论证是主观的。就个人而言,我发现一个干净的声明迭代器不太可读。并且它并不重要,因为迭代器是同时迭代和删除的安全方式。
答案 1 :(得分:9)
这些答案似乎都没有说明迭代器的原因。创建迭代器设计模式是因为对象应该控制它自己的状态(除了可能只有公共属性的值对象)。
假设我们有一个包含数组的对象,并且该对象中有一个接口可以向该数组添加项目。但你做了类似的事情:
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的引用,并将项添加到数组中,不带调用item.doSomething();这就是为什么你不应该返回对数组的引用,而是返回它的迭代器。可以从数组中获取任何项目,但它无法操纵原始数组。因此,MyClass对象仍然可以控制它自己的状态。
这就是发明迭代器的真正原因。
答案 2 :(得分:2)
是的,我们需要。 ArrayList只是List接口的一个实现,所以你的代码通常会处理一个列表,甚至不知道它是一个ArrayList。此外,新的for-loop语法在内部使用迭代器。
答案 3 :(得分:1)
使用迭代器可以避免在LinkedList上使用get(index)的错误(非常慢)。当列表的实现未知时,它是有意义的,只需使用迭代器。关于ArrayList,使用迭代器仍将使用get(index)实现最接近的性能。
因此,在性能方面使用迭代器进行迭代是一种很好的做法。
答案 4 :(得分: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
}
答案 5 :(得分:-1)
使用迭代器,代码的可读性要差得多。
这完全是你的意见,我不赞同。
有可能引发难以调试的ConcurrentModificationException。
无论您是否使用迭代器,都可能存在。该异常会告诉您一些有关您的代码的有用信息,否则您可能会完全错过,这更难调试。
我个人更喜欢能够准确地编写ArrayList和LinkedList之间的代码,并让编译器或API实现细节。
道德观点是,你不应该将你自己不支持的意见作为既定事实。