为什么我们需要在Java中的ArrayList上使用iterator?

Kar*_* Rk 34 java iterator arraylist

我正在阅读" 我们是否需要在ArrayList上使用迭代器? " 这一问题中提到的答案.

在答案中,用户声明了这样的话:"使用ArrayLists的迭代器的一个大用例是当你想在迭代时删除元素".

即使在Java中使用ArrayList的remove方法也可以实现这一点.我的问题是为什么我们需要ArrayList中的迭代器?

考虑一下代码:

import java.util.*;
public class ocajp66 {
    public static void main(String[] args) {
        ArrayList a = new ArrayList();
        for (int i = 0; i < 10; i++) {
            a.add(i);
        }
        System.out.printf("BEFORE ITERATOR\n");
        for (int i = 0; i < a.size(); i++) {
            System.out.printf("I:%d\n", a.get(i));
        }
        System.out.printf("AFTER ITERATOR\n");
        Iterator i = a.iterator();
        while (i.hasNext()) {
            System.out.printf("I:%d\n", i.next());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

任何人都可以解释迭代器的重要性吗?如果你能用代码解释我会很棒.

Dev*_*ked 53

如您所述,当您想要在迭代数组内容时删除内容时使用迭代器.如果你不使用迭代器但只是有一个for循环并在其中使用remove方法,你会得到异常,因为迭代时数组的内容会发生变化.例如:你可能认为在for循环开始时数组大小是10但是一旦你移除了东西就不会这样了.所以当你到达最后一个循环时可能会有IndexOutofBoundsException等.

  • 这不是正确的答案.迭代器是一种封装数组的方法,因此您无法编辑其内容.你刚才所说的是在迭代器中添加的. (3认同)
  • 这就是为什么你使用array.size()作为for循环条件而不是幻数. (3认同)

Ste*_*n C 14

显然,ArrayList类似API的API可以在没有该iterator()方法的情况下工作.但是,a ArrayList是a Collection并且该iterator()方法在Collection接口中定义...因此ArrayList 必须实现它.

关于从a中删除的一点ArrayList是,通过索引进行操作需要一些思考:

    for (int i = 0; 
         i < a.size(); // Hoist this at your peril
         i++) {
        if (a.get(i) == something) {
            a.remove(i);
            i--;  // Leave this out at your peril
        }
    }
Run Code Online (Sandbox Code Playgroud)

如果你需要删除从循环中调用的方法中的list元素,情况会变得更糟......因为方法必须说它已经删除了一个元素,以便调用者可以调整循环索引.

第三个原因iterator是上个好东西ArrayList是它允许你使用Java 5的for (type var : iterable) ...语法.

底线是您不必在实例使用迭代器ArrayList.如果你不想,那就不要了.


sco*_*ttb 6

这是一个如何以几种不同的方式获得所需结果的示例.这种冗余并不是Java独有的.

  • for(int i = 0; i <myArray.length; i ++){...}

这种语法是在早期版本的Java中引入的.它迭代for {}循环中的常规Java数组.这通常是安全的,因为Java数组是固定长度的,因此"Index Out of Bounds"异常是不可能的.

  • for(int i = 0; i <myArrayList.size(); i ++ {...}

在引入ArrayList的Collections API之后,此语法反映了Java的更高版本.如上所述,实现Collection接口的类必须实现Iterator,但您不必使用它.这对于{}循环没有,但这里的危险是ArrayLists不是固定大小.如果它应该在for循环的主体中收缩,并且可能导致异常.

  • for(MyArrayType t:myArrayList){}

此语法也在Java的更高版本中发布.它被称为增强的for循环.通过实现Iterable接口提供Iterator的任何集合类都可以利用此语法.这允许迭代集合中的项而无需显式实例化Iterator.在JavaFX应用程序中使用它的一种最喜欢的方法是循环访问一组控件以将属性设置为值,例如.重置一组TextFields的内容:

for (TextField tf : new TextField[] { txtf1, txtf2, txtf3, txtfa, txtfb, txtfc}) {
    tf.setText("");
}
Run Code Online (Sandbox Code Playgroud)
  • while(myCollectionIterator.hasNext()){}

您始终可以显式实例化Iterator.当集合大小发生变化时(从Collection自己的方法),这是安全的.可以肯定地说,Iterator是Iterable接口的一个属性,而不是核心Java语言的一个特性.但是,由于以后的Java版本,您仍然可以将它用作类似语言的功能(在增强的for循环中).

这些结构提供了冗余,但它们并不相同.每种细微差别使得在给定时间内特别有用.你应该使用所有这些.