【问题标题】:why there is no add method in Iterator interface为什么Iterator接口中没有add方法
【发布时间】:2012-06-27 03:14:29
【问题描述】:

IteratorSun 中添加了remove 方法来删​​除集合中最后访问的元素。为什么没有 add 方法向集合中添加新元素?它可能对集合或迭代器产生什么样的副作用?

【问题讨论】:

  • 我认为你有重复:stackoverflow.com/questions/993025/…
  • @mihaisimi -- 不,这真的是一个不同的问题。
  • 是的,你是对的。仍然 coobird 在该线程上提供了一个很好的答案。

标签: java collections iterator


【解决方案1】:

好的,我们开始:

设计常见问题中明确说明了答案:

为什么不提供一个 Iterator.add 方法?

语义不清楚,因为 Iterator 的合约不保证迭代的顺序。但是请注意,ListIterator 确实提供了一个加法操作,因为它确实保证了迭代的顺序。

http://docs.oracle.com/javase/1.4.2/docs/guide/collections/designfaq.html#10

【讨论】:

  • 抱歉迟到了。但例如 LinkedHashSet 确实保持插入顺序。为什么他们当时不为它制作 Iterator 呢? Add() 方法在这种情况下可以正常工作,对吧?
  • @Stefan 阅读了这个问题:stackoverflow.com/questions/26277042/… 涵盖了该案例
【解决方案2】:

迭代器的唯一目的是枚举一个集合。所有集合都包含 add() 方法以满足您的目的。添加到迭代器是没有意义的,因为集合可能会或可能不会被排序(在 HashSet 的情况下)。

编辑: 在处理另一个问题时,我想出了另一个原因,即 Iterator 缺少 add() 方法。查看 ArrayList(第 111 行)和 HashMap(第 149 行)的内部结构,我们看到实现只是围绕对象数组的几个方法。现在我们考虑如何在内存中处理数组。

这是一个由 5 个元素组成的数组。但是,有六个指标。这个数组中的字母“a”被列为元素 0,因为为了像计算机一样从左到右读取它,您必须从索引 0 开始。现在,如果我们正在遍历这个数组(是的,集合,但归结为一个数组),我们将从索引 0 开始并继续索引 1。此时在迭代器中,我们要调用 add("f");。此时,让我们比较一下add()remove() 的含义。 remove() 会在数组中留下一个空格,这很容易跳过,因为我们可以立即识别出它不是成员。另一方面,add() 会放入一个以前没有的新元素。这将影响我们正在迭代的数组的长度。当我们到达最后一个元素时会发生什么?我们能否保证它存在(即数组没有超过the maximum size)?

总而言之,一种或另一种方式的参数都有有效点,但最重要的是add() 方法的行为在所有情况下都没有得到很好的定义。 Sun 必须选择在哪里限制功能,他们选择不包含此方法。

【讨论】:

  • “因为该系列可能会或可能不会被订购” - 请您详细说明一下。谢谢
  • 我收到了你的声明:-)。谢谢
  • HashSet 不保证其成员的顺序。如果您正在迭代它以尝试找到插入值的点,那么您刚刚击败了迭代器的点。
  • 但是从Iterator 中删除也没有意义。然而remove() 的存在使得(可选地)可以在不使Iterator 失效的情况下删除元素。不应该存在add(E) 以便在不使Iterator 无效的情况下添加元素吗?当然,您可以在迭代后将元素添加到Iterable。但移除元素也是如此。我认为Iterator 有一个remove() 方法,因为与add(T) 相比,它通常高效、易于实现和明确定义。
  • @Robert 这是一个不可靠的论点,我承认,但我同意你的最后一句话。作为他(第二个)答案中的 jontro 链接,设计常见问题解答甚至没有给出很好的解释。我相信remove() 方法在Iterator 中的位置比add(T) 方法要多。底线是,出于某种原因,Sun 选择在该特定点限制 Iterator 的功能。
【解决方案3】:

如果您正在处理一个列表,您可以使用ListIterator,它提供了添加和删除操作。

【讨论】:

  • 实际上并没有回答这个问题。但是是的,Iterator 没有实现add,因为它不是ListIterator
【解决方案4】:

我想再补充一点。

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() 将有机会运行一个无限循环。 并且简单地我们使用迭代器来遍历元素,而不是陷入无限循环。

【讨论】:

    【解决方案5】:

    迭代器只有一个指向下一个元素的指针。其中 ListIterator 也有指向前一个元素的指针(请记住,它可以向后遍历)。

    【讨论】:

      【解决方案6】:

      因为 ListIterator 维护插入顺序,因此您可以到达要添加的位置。迭代器不关心顺序,所以如果它在迭代时将对象添加到过去的值中,那将是一场灾难。这就是迭代器只被赋予 remove() 方法的原因,因为你有一个特定的对象和从哪里移除。

      【讨论】:

        【解决方案7】:

        我想不出add() 不能包含在Iterator 中的任何理论上的原因。正如Iterator 可以允许通过自身从集合中删除元素一样,它也可以被设计为处理以相同方式添加的元素。

        但我会说,在我所有的 Java 编程生涯中——超过 15 年! -- 我从不想要Iterator.add() 方法。所以我怀疑它根本没有那么有用。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-09-30
          • 2016-12-31
          • 2016-07-12
          • 2020-06-07
          • 2011-02-24
          • 2013-11-16
          • 2019-01-10
          • 1970-01-01
          相关资源
          最近更新 更多