在Iterator
Sun 中添加了 remove 方法来删除集合中最后访问的元素。为什么没有 add 方法向集合中添加新元素?它可能对集合或迭代器产生什么样的副作用?
7 回答
好的,我们开始:
设计常见问题解答中明确说明了答案:
为什么不提供 Iterator.add 方法?
语义尚不清楚,因为 Iterator 的合同不保证迭代的顺序。但是请注意,ListIterator 确实提供了添加操作,因为它确实保证了迭代的顺序。
http://docs.oracle.com/javase/1.4.2/docs/guide/collections/designfaq.html#10
Iterator 的唯一目的是枚举一个集合。所有集合都包含add()
为您服务的方法。添加到 Iterator 是没有意义的,因为集合可能会或可能不会被排序(在 a 的情况下HashSet
)。
编辑:在解决另一个问题时,我想出了另一个Iterator
缺少add()
方法的原因。查看ArrayList
(第 111 行)和HashMap
(第 149 行)的底层,我们看到实现只是围绕对象数组的几个方法。现在我们考虑如何在内存中处理数组。
这是一个包含 5 个元素的数组。但是,有六个指标。这个数组中的字母“a”被列为元素 0,因为为了像计算机一样从左到右读取它,您必须从索引 0 开始。现在,如果我们正在遍历这个数组(是的,集合,但归结为一个数组),我们将从索引 0 开始并继续索引 1。此时在迭代器中,我们要调用add("f");
. 在这一点上,让我们比较 和 的add()
含义remove()
。remove()
会在数组中留下一个空格,这很容易跳过,因为我们可以立即识别它不是成员。另一方面,add()
会放入一个以前没有的新元素。这将影响我们正在迭代的数组的长度。当我们到达最后一个元素时会发生什么?我们甚至可以保证它在那里(也就是说,数组没有超过最大大小)吗?
总而言之,一种或另一种方式的参数都有有效的点,但底线是add()
方法的行为在所有情况下都没有得到很好的定义。Sun 不得不选择在哪里限制功能,他们选择不包括这种方法。
如果您正在处理列表,则可以使用提供添加和删除操作的ListIterator 。
我想再补充一点。
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("aa");
arrayList.add("ab");
Iterator<String> iterator = arrayList.iterator();
while (iterator.hasNext()) {
String string = (String) iterator.next();
}
这里迭代器需要最大到最大 2 次迭代来完成它的迭代。所以迭代器需要一定的时间才能在 N 时间内完成它的迭代。
但是如果我们添加add()
方法会怎样:
while (iterator.hasNext()) {
String string = (String) iterator.next();
iterator.add("adding this data means iterator will always have next
element.")
}
因此添加add()
迭代器将有机会运行无限循环。并且简单地我们使用迭代器来遍历元素,而不是陷入无限循环。
迭代器只有一个指向下一个元素的指针。其中 ListIterator 也有指向前一个元素的指针(请记住,它可以向后遍历)。
因为 ListIterator 维护插入顺序,因此您可以到达要添加的位置。迭代器不关心顺序,所以如果它在迭代时将对象添加到过去的值中,那将是一场灾难。这就是迭代器只被赋予 remove() 方法的原因,因为你有一个特定的对象和从哪里删除。
我想不出任何理论上的理由为什么add()
不能被包含在Iterator
. 正如Iterator
can 允许通过自身从集合中删除元素一样,它可以被设计为处理以相同方式添加的元素。
但我会说,在我所有的 Java 编程生涯中——超过 15 年!——我从来没有想要一种Iterator.add()
方法。所以我怀疑它根本没有那么有用。