java集合(2) 什么是迭代器

      学习是循序渐进的,很多以前经常用的东西都没有从基础开始发掘这个知识,就像新循环,知道它的底层是迭代器,但是很少用到,所以也一知半解。就是想在基础上重新学习一次,对以往的知识有个系统的学习。今天转载俩篇关于迭代器的知识,方便以后自己查看。

    什么是迭代器?

为了方便的处理集合中的元素,Java中出现了一个对象,该对象提供了一些方法专门处理集合中的元素.例如删除和获取集合中的元素.该对象就叫做迭代器(Iterator).

对 Collection 进行迭代的类,称其为迭代器。还是面向对象的思想,专业对象做专业的事情,迭代器就是专门取出集合元素的对象。但是该对象比较特殊,不能直接创建对象(通过new),该对象是以内部类的形式存在于每个集合类的内部。

如何获取迭代器?Collection接口中定义了获取集合类迭代器的方法(iterator()),所以所有的Collection体系集合都可以获取自身的迭代器。

1.Iterable

正是由于每一个容器都有取出元素的功能。这些功能定义都一样,只不过实现的具体方式不同(因为每一个容器的数据结构不一样)所以对共性的取出功能进行了抽取,从而出现了Iterator接口。而每一个容器都在其内部对该接口进行了内部类的实现。也就是将取出方式的细节进行封装。

Jdk1.5之后添加的新接口, Collection的父接口实现了Iterable的类就是可迭代的.并且支持增强for循环。该接口只有一个方法即获取迭代器的方法iterator()可以获取每个容器自身的迭代器Iterator。(Collection)集合容器都需要获取迭代器(Iterator)于是在5.0后又进行了抽取将获取容器迭代器的iterator()方法放入到了Iterable接口中。Collection接口进程了Iterable,所以Collection体系都具备获取自身迭代器的方法,只不过每个子类集合都进行了重写(因为数据结构不同)

2.Iterator 

iterator() 返回该集合的迭代器对象

该类主要用于遍历集合对象,该类描述了遍历集合的常见方法

1java.lang. Itreable  

---| Itreable      接口 实现该接口可以使用增强for循环

        ---| Collection 描述所有集合共性的接口

             ---| List接口     可以有重复元素的集合

             ---| Set接口     不可以有重复元素的集合

public interface Iterable<T>

Itreable   该接口仅有一个方法,用于返回集合迭代器对象。

  Iterator<T> iterator() 返回集合的迭代器对象

 

Iterator接口定义的方法

[java]  view plain  copy
  1. Itreator    该接口是集合的迭代器接口类,定义了常见的迭代方法  
  2.     1boolean hasNext()   
  3.                         判断集合中是否有元素,如果有元素可以迭代,就返回true。  
  4.     2: E next()    
  5.                         返回迭代的下一个元素,注意: 如果没有下一个元素时,调用  
  6. next元素会抛出NoSuchElementException  
  7.   
  8.     3: void remove()  
  9.                         从迭代器指向的集合中移除迭代器返回的最后一个元素(可选操  
  10. 作)。  

思考:为什么next方法的返回类型是Object的呢? 

为了可以接收任意类型的对象,那么返回的时候,不知道是什么类型的就定义为object

3.迭代器的遍历

第一种方式:while循环

[java]  view plain  copy
  1. public static void main(String[] args) {  
  2.         ArrayList list = new ArrayList();  
  3.         // 增加:add() 将指定对象存储到容器中  
  4.         list.add("计算机网络");  
  5.         list.add("现代操作系统");  
  6.         list.add("java编程思想");  
  7.         list.add("java核心技术");  
  8.         list.add("java语言程序设计");  
  9.         System.out.println(list);  
  10.         Iterator it = list.iterator();  
  11.         while (it.hasNext()) {  
  12.             String next = (String) it.next();  
  13.             System.out.println(next);  
  14.         }  
  15.     }  
第二种方式:for循环

[java]  view plain  copy
  1. public class Demo2 {  
  2.     public static void main(String[] args) {  
  3.         ArrayList list = new ArrayList();  
  4.         // 增加:add() 将指定对象存储到容器中  
  5.         list.add("计算机网络");  
  6.         list.add("现代操作系统");  
  7.         list.add("java编程思想");  
  8.         list.add("java核心技术");  
  9.         list.add("java语言程序设计");  
  10.         System.out.println(list);  
  11.   
  12.         for (Iterator it = list.iterator(); it.hasNext();) {  
  13.              //迭代器的next方法返回值类型是Object,所以要记得类型转换。  
  14.             String next = (String) it.next();  
  15.             System.out.println(next);  
  16.         }  
  17.     }  
  18. }  

需要取出所有元素时,可以通过循环,java 建议使用for 循环。因为可以对内存进行一下优化。

第三种方式:使用迭代器清空集合

[java]  view plain  copy
  1. public class Demo1 {  
  2.     public static void main(String[] args) {  
  3.         Collection coll = new ArrayList();  
  4.         coll.add("aaa");  
  5.         coll.add("bbb");  
  6.         coll.add("ccc");  
  7.         coll.add("ddd");  
  8.         System.out.println(coll);  
  9.         Iterator it = coll.iterator();  
  10.         while (it.hasNext()) {  
  11.             it.next();  
  12.             it.remove();  
  13.         }  
  14.         System.out.println(coll);  
  15.     }  
  16. }  
需要注意的细节如下:

细节一:如果迭代器的指针已经指向了集合的末尾,那么如果再调用next()会返回NoSuchElementException异常

[java]  view plain  copy
  1. public class Demo2 {  
  2.     public static void main(String[] args) {  
  3.         ArrayList list = new ArrayList();  
  4.         // 增加:add() 将指定对象存储到容器中  
  5.         list.add("计算机网络");  
  6.         list.add("现代操作系统");  
  7.         list.add("java编程思想");  
  8.         list.add("java核心技术");  
  9.         list.add("java语言程序设计");  
  10.         System.out.println(list);  
  11.   
  12.         Iterator it = list.iterator();  
  13.         while (it.hasNext()) {  
  14.             String next = (String) it.next();  
  15.             System.out.println(next);  
  16.         }  
  17.         // 迭代器的指针已经指向了集合的末尾  
  18.         // String next = (String) it.next();  
  19.         // java.util.NoSuchElementException  
  20.     }  
  21. }  

细节二:

 如果调用remove之前没有调用next是不合法的,会抛出IllegalStateException

[java]  view plain  copy
  1. public class Demo2 {  
  2.     public static void main(String[] args) {  
  3.         ArrayList list = new ArrayList();  
  4.         // 增加:add() 将指定对象存储到容器中  
  5.         list.add("计算机网络");  
  6.         list.add("现代操作系统");  
  7.         list.add("java编程思想");  
  8.         list.add("java核心技术");  
  9.         list.add("java语言程序设计");  
  10.         System.out.println(list);  
  11.   
  12.         Iterator it = list.iterator();  
  13.         while (it.hasNext()) {  
  14.             // 调用remove之前没有调用next是不合法的  
  15.             // it.remove();  
  16.             // java.lang.IllegalStateException  
  17.             String next = (String) it.next();  
  18.             System.out.println(next);  
  19.         }  
  20.   
  21.     }  
  22. }  

4.迭代器的原

查看ArrayList源码

[java]  view plain  copy
  1. private class Itr implements Iterator<E> {  
  2.   
  3.         int cursor = 0;  
  4.   
  5.         int lastRet = -1;  
  6.   
  7.         int expectedModCount = modCount;  
  8.   
  9.         public boolean hasNext() {  
  10.             return cursor != size();  
  11.         }  
  12.   
  13.         public E next() {  
  14.             checkForComodification();  
  15.             try {  
  16.                 E next = get(cursor);  
  17.                 lastRet = cursor++;  
  18.                 return next;  
  19.             } catch (IndexOutOfBoundsException e) {  
  20.                 checkForComodification();  
  21.                 throw new NoSuchElementException();  
  22.             }  
  23.         }  
  24.   
  25.         public void remove() {  
  26.             if (lastRet == -1)  
  27.                 throw new IllegalStateException();  
  28.             checkForComodification();  
  29.   
  30.             try {  
  31.                 AbstractList.this.remove(lastRet);  
  32.                 if (lastRet < cursor)  
  33.                     cursor--;  
  34.                 lastRet = -1;  
  35.                 expectedModCount = modCount;  
  36.             } catch (IndexOutOfBoundsException e) {  
  37.                 throw new ConcurrentModificationException();  
  38.             }  
  39.         }  
  40.   
  41.           
  42.     }  

注意:1.在对集合进行迭代过程中,不允许出现迭代器以外的对元素的操作,因为这样会产生安全隐患,java会抛出异常并发修改异常(ConcurrentModificationException),普通迭代器只支持在迭代过程中的删除动作。

     2.ConcurrentModificationException: 当一个集合在循环中即使用引用变量操作集合又使用迭代器操作集合对象, 会抛出该异常。

[java]  view plain  copy
  1. public class Demo1 {  
  2.     public static void main(String[] args) {  
  3.         Collection coll = new ArrayList();  
  4.         coll.add("aaa");  
  5.         coll.add("bbb");  
  6.         coll.add("ccc");  
  7.         coll.add("ddd");  
  8.         System.out.println(coll);  
  9.         Iterator it = coll.iterator();  
  10.         while (it.hasNext()) {  
  11.             it.next();  
  12.             it.remove();  
  13.             coll.add("abc"); // 出现了迭代器以外的对元素的操作  
  14.         }  
  15.         System.out.println(coll);  
  16.     }  
  17. }  

如果是List集合,想要在迭代中操作元素可以使用List集合的特有迭代器ListIterator,该迭代器支持在迭代过程中,添加元素和修改元素。

5.List特有的迭代器ListIterator

public interface ListIterator extends Iterator

ListIterator<E> listIterator()

[java]  view plain  copy
  1. ---| Iterator  
  2.         hasNext()  
  3.         next()  
  4.         remove()  
  5.        ------| ListIterator Iterator子接口 List专属的迭代器  
  6.                   add(E e)    将指定的元素插入列表(可选操作)。该元素直接插入到 next 返回的下一个元素的前面(如果有)  
  7.                   void set(E o)   用指定元素替换 next 或 previous 返回的最后一个元素  
  8.                   hasPrevious()    逆向遍历列表,列表迭代器有多个元素,则返回 true。  
  9.                   previous()       返回列表中的前一个元素。  

Iterator在迭代时,只能对元素进行获取(next())和删除(remove())的操作。

对于 Iterator 的子接口ListIterator 在迭代list 集合时,还可以对元素进行添加

(add(obj)),修改set(obj)的操作。

[java]  view plain  copy
  1. public class Demo2 {  
  2.     public static void main(String[] args) {  
  3.         ArrayList list = new ArrayList();  
  4.         // 增加:add() 将指定对象存储到容器中  
  5.         list.add("计算机网络");  
  6.         list.add("现代操作系统");  
  7.         list.add("java编程思想");  
  8.         list.add("java核心技术");  
  9.         list.add("java语言程序设计");  
  10.         System.out.println(list);  
  11.          // 获取List专属的迭代器  
  12.         ListIterator lit = list.listIterator();  
  13.   
  14.         while (lit.hasNext()) {  
  15.             String next = (String) lit.next();  
  16.             System.out.println(next);  
  17.         }  
  18.   
  19.     }  
  20. }  

倒序遍历

[java]  view plain  copy
  1. public class Demo2 {  
  2.     public static void main(String[] args) {  
  3.         ArrayList list = new ArrayList();  
  4.         // 增加:add() 将指定对象存储到容器中  
  5.         list.add("计算机网络");  
  6.         list.add("现代操作系统");  
  7.         list.add("java编程思想");  
  8.         list.add("java核心技术");  
  9.         list.add("java语言程序设计");  
  10.         System.out.println(list);  
  11.         // 获取List专属的迭代器  
  12.         ListIterator lit = list.listIterator();  
  13.         while (lit.hasNext()) {  
  14.             String next = (String) lit.next();  
  15.             System.out.println(next);  
  16.         }  
  17.         System.out.println("***************");  
  18.         while (lit.hasPrevious()) {  
  19.             String next = (String) lit.previous();  
  20.             System.out.println(next);  
  21.         }  
  22.   
  23.     }  
  24. }  

Set方法:用指定元素替换 next 或 previous 返回的最后一个元素

[java]  view plain  copy
  1. public class Demo2 {  
  2.     public static void main(String[] args) {  
  3.         ArrayList list = new ArrayList();  
  4.         // 增加:add() 将指定对象存储到容器中  
  5.         list.add("计算机网络");  
  6.         list.add("现代操作系统");  
  7.         list.add("java编程思想");  
  8.         list.add("java核心技术");  
  9.         list.add("java语言程序设计");  
  10.         System.out.println(list);  
  11.   
  12.         ListIterator lit = list.listIterator();  
  13.         lit.next(); // 计算机网络  
  14.         lit.next(); // 现代操作系统  
  15.         System.out.println(lit.next()); // java编程思想  
  16.         //用指定元素替换 next 或 previous 返回的最后一个元素  
  17.         lit.set("平凡的世界");// 将java编程思想替换为平凡的世界  
  18.         System.out.println(list);  
  19.   
  20.     }  
  21. }  

add方法将指定的元素插入列表,该元素直接插入到 next 返回的元素的后面

[java]  view plain  copy
  1. public class Demo2 {  
  2.     public static void main(String[] args) {  
  3.         ArrayList list = new ArrayList();  
  4.         // 增加:add() 将指定对象存储到容器中  
  5.         list.add("计算机网络");  
  6.         list.add("现代操作系统");  
  7.         list.add("java编程思想");  
  8.         list.add("java核心技术");  
  9.         list.add("java语言程序设计");  
  10.         System.out.println(list);  
  11.   
  12.         ListIterator lit = list.listIterator();  
  13.         lit.next(); // 计算机网络  
  14.         lit.next(); // 现代操作系统  
  15.         System.out.println(lit.next()); // java编程思想  
  16.         // 将指定的元素插入列表,该元素直接插入到 next 返回的元素的后  
  17.         lit.add("平凡的世界");// 在java编程思想后添加平凡的世界  
  18.         System.out.println(list);  
  19.   
  20.     }  

上面是转载的关于迭代器的最基础的知识,看到这里心中产生了疑惑,Iterator和Iterable有什么区别呢?

Java中Iterator与Iterable的区别

Iterable的定义:

java.lang包

[java]  view plain  copy
  1. /** 
  2.  * Implementing this interface allows an object to be the target of 
  3.  * the "foreach" statement. 
  4.  * 
  5.  * @param <T> the type of elements returned by the iterator 
  6.  * 
  7.  * @since 1.5 
  8.  */  
  9. public interface Iterable<T> {  
  10.   
  11.     /** 
  12.      * Returns an iterator over a set of elements of type T. 
  13.      * 
  14.      * @return an Iterator. 
  15.      */  
  16.     Iterator<T> iterator();  
  17. }  

Iterator的定义:

java.util包:

[java]  view plain  copy
  1. public interface Iterator<E> {  
  2.     boolean hasNext();  
  3.   
  4.     E next();  
  5.   
  6.     void remove();  
  7. }  

Iterator是迭代器类,而Iterable是为了只要实现该接口就可以使用foreach,进行迭代。

Iterable中封装了Iterator接口,只要实现了Iterable接口的类,就可以使用Iterator迭代器了。

集合Collection、List、Set都是Iterable的实现类,所以他们及其他们的子类都可以使用foreach进行迭代。

那为什么这些集合类不直接实现Iterator呢?

Iterator中和核心的方法next(),hasnext(),remove(),都是依赖当前位置,如果这些集合直接实现Iterator,则必须包括当前迭代位置的指针。当集合在方法间进行传递的时候,由于当前位置不可知,所以next()之后的值,也不可知。而当实现Iterable则不然,每次调用都返回一个从头开始的迭代器,各个迭代器之间互不影响。



猜你喜欢

转载自blog.csdn.net/qq_35583089/article/details/80305985