Java——深入理解Java中的迭代器

概述:

迭代器模式:就是提供一种方法对一个容器对象中的各个元素进行访问,而又不暴露该对象容器的内部细节。

Java集合框架的集合类,我们有时候称之为容器。容器的种类有很多种,比如ArrayList、LinkedList、HashSet...,每种容器都有自己的特点,ArrayList底层维护的是一个数组;LinkedList是链表结构的;HashSet依赖的是哈希表,每种容器都有自己特有的数据结构。

因为容器的内部结构不同,很多时候可能不知道该怎样去遍历一个容器中的元素。所以为了使对容器内元素的操作更为简单,Java引入了迭代器模式! 

把访问逻辑从不同类型的集合类中抽取出来,从而避免向外部暴露集合的内部结构

为什么要引入迭代器的概念?

对于数组我们使用的是下标来进行处理的:

int array[] = new int[3];    
for (int i = 0; i < array.length; i++) {
    System.out.println(array[i]);
}

对ArrayList的处理:

List<String> list = new ArrayList<String>();
for(int i = 0 ; i < list.size() ;  i++){
    String string = list.get(i);}

对于这两种方式,我们总是都知道它的内部结构,访问代码和集合本身是紧密耦合的,无法将访问逻辑从集合类和客户端代码中分离出来。不同的集合会对应不同的遍历方法,客户端代码无法复用。所以才有Iterator,它总是用同一种逻辑来遍历集合。所有的内部状态都由Iterator来维护。客户端不用直接和集合进行打交道,而是控制Iterator就可以遍历集合,从而避免向外部暴露集合的内部结构。

代码实现:

在Java中Iterator为一个接口,它只提供了迭代的基本规则。迭代器在迭代期间可以从集合中移除元素(必须使用迭代器的删除方法)

其接口定义如下:

public interface Iterator<E> {
    boolean hasNext();//判断是否存在下一个对象元素
    E next();//获取下一个元素
    void remove();//移除元素
}

使用迭代器遍历集合:

public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("张三1");
        list.add("张三2");
        list.add("张三3");
        list.add("张三4");
        
        List<String> linkList = new LinkedList<String>();
        linkList.add("link1");
        linkList.add("link2");
        linkList.add("link3");
        linkList.add("link4");
        
        Set<String> set = new HashSet<String>();
        set.add("set1");
        set.add("set2");
        set.add("set3");
        set.add("set4");
        //使用迭代器遍历ArrayList集合
        Iterator<String> listIt = list.iterator();
        while(listIt.hasNext()){
            System.out.println(listIt.hasNext());
        }
        //使用迭代器遍历Set集合
        Iterator<String> setIt = set.iterator();
        while(setIt.hasNext()){
            System.out.println(listIt.hasNext());
        }
        //使用迭代器遍历LinkedList集合
        Iterator<String> linkIt = linkList.iterator();
        while(linkIt.hasNext()){
            System.out.println(listIt.hasNext());
        }
}

Iterator遍历时不可以删除集合中的元素:

import java.util.*;    //导包  
public class Test1 {  
    public static void main(String[] args)  
    {  
    	ArrayList <Clerk> al=new ArrayList<>();    //创建集合
    	al.add(new Clerk("周卫国",30,5000));        //添加对象
    	al.add(new Clerk("李云龙",30,5000));
    	al.add(new Clerk("诸葛亮",30,5000));
    	al.add(new Clerk("张小凡",30,5000));
    	al.add(new Clerk("泛型",30,5000));
    	al.add(new Clerk("集合",30,5000));
    	System.out.println("---------遍历集合");
    	Iterator <Clerk> listIt = al.iterator();    //创建迭代器
    	while(listIt.hasNext())                     //遍历
    	{
    		Clerk temp = listIt.next();        
    		if(temp.getName().equals("李云龙"))//找到李云龙
    			al.remove(1);             //删除对象
    	                //或者是a1.add(new Clerk("1",2,3)) //又或者是添加对象
        }
    	System.out.println("---------输出集合");
    	for(Clerk x:al)
    	{
    		System.out.println(x.getName()+" "+x.getAge()+" "+x.getSalary());
    	}
    }
}  
class Clerk                                                   //定义员工类  
{  
    private String name;  
    private int age;  
    private double salary;  
    Clerk(String name,int age,double salary)  
    {  
        this.name=name;  
        this.age=age;  
        this.salary=salary;  
    }  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
    public int getAge() {  
        return age;  
    }  
    public void setAge(int age) {  
        this.age = age;  
    }  
    public double getSalary() {  
        return salary;  
    }  
    public void setSalary(double salary) {  
        this.salary = salary;  
    }  
}  

输出结果:

---------遍历集合
Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
	at java.util.ArrayList$Itr.next(Unknown Source)
	at text.Test1.main(Test1.java:17)

在使用Iterator的时候禁止对所遍历的容器进行改变其大小结构的操作。例如: 在使用Iterator进行迭代时,如果对集合进行了add、remove操作就会出现ConcurrentModificationException异常。

因为在你迭代之前,迭代器已经被通过list.itertor()创的,就会给出善意的提醒(抛出ConcurrentModificationException异常)建出来了,如果在迭代的过程中,又对list进行了改变其容器大小的操作,那么Java就会给出异常。因为此时Iterator对象已经无法主动同步list做出的改变,Java会认为你做出这样的操作是线程不安全

使用Foreach时对集合的结构进行修改会出现异常:

因为foreach要依赖于Iterable接口返回的Iterator对象,所以从本质上来讲,Foreach其实就是在使用迭代器,在使用foreach遍历时对集合的结构进行修改,和在使用Iterator遍历时对集合结构进行修改本质上是一样的,所以同样的也会抛出异常。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狮子座的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值