【问题标题】:How for-each loop knows where to start?for-each 循环如何知道从哪里开始?
【发布时间】:2013-09-24 22:48:17
【问题描述】:

Iterator保证有以下方法:

  • hasNext()
  • 下一个()
  • 删除(可选

for-each 循环遍历iterable 类对象时,它如何知道从哪个对象开始?上述方法提供了清晰的前进路径,但什么指向起始元素?

For-each 保证遍历所有相关对象。根据一个类及其next() 实现,从哪里开始可能非常重要(考虑forward linked list 或任何其他具有root 元素的实现)。

它是如何工作的?

如果我的问题没有意义,请解释原因。

【问题讨论】:

  • 它使用next() 在第一次迭代中返回的任何内容...
  • 你从容器中获取的迭代器被初始化为start。
  • 您可以定义在 Iterator 实现中的起点。例如,对于Lists,您有一个从第一个元素到最后一个元素的 直接 迭代器,以及一个从最后一个元素到第一个元素的反向迭代器。
  • @LuiggiMendoza - 我的自己的自定义迭代器怎么样?起点逻辑到底应该在哪里实现?就像在 another question 中一样,你在帮助我。
  • 在这种情况下,您的迭代器将从您可以访问的第一个 Thing 开始。然后,这取决于您希望如何浏览该树。如 cmets 中所述,您可以实现前缀、中缀或后缀遍历。

标签: java foreach iterator


【解决方案1】:

From the spec:

官方称为增强的for 语句 (for(E e: Iterable<E> iterable)) 被编译器翻译成以下代码的等效项:

E e;
for(Iterator<E> it = iterable.iterator(); it.hasNext(); ) {
    e = it.next();
    // contents of your for loop
}

循环的行为就像你用显式的Iterator 编写它一样,所以增强的for 循环的“起点”是iterable.iterator() 本来应该开始的任何地方。

【讨论】:

    【解决方案2】:

    您可能想查看ArrayListIterator 实现,Itr 内部类。

    private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;
    
        public boolean hasNext() {
            return cursor != size;
        }
    
        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }
        ...
    }
    

    cursor 默认初始化为0。您可以使用cursor 访问ArrayList 对象的支持数组中的元素(它是一个内部类,它可以访问该字段)。

    类似的逻辑适用于Iterator 的其他实现。它始终取决于底层数据结构。再举一个例子,Set 不应该有排序,但它确实实现了Iterator。必须决定迭代器从哪里开始。

    【讨论】:

      【解决方案3】:

      foreach 是 for 循环从 first 到 last 的简写。

      【讨论】:

      • 什么定义了从 Java Collection 派生的自定义类的“first”和“last” ?
      【解决方案4】:

      这一切都取决于你的收藏。

      如果您的集合是一个列表(通常是ArrayListLinkedList),那么迭代器将根据它们的插入方式按列表顺序排列。

      如果是 Map 或 Set,则很难预测其成员的顺序。如果您使用的是 Map 或 Set,则实际上不应指望任何可预测的排序,因为它不符合这些集合的目的。但是,如果您需要特定订单但还需要 Map 或 Set 的功能,则可以使用 LinkedHashMapLinkedHashSet

      【讨论】:

      • 如果我没有集合而只是一个实现Iterable的类怎么办?
      猜你喜欢
      • 1970-01-01
      • 2011-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-09
      • 2017-07-03
      • 1970-01-01
      • 2014-10-03
      相关资源
      最近更新 更多