深入理解迭代器

483 查看

一,迭代器的原理


我们大家都知道迭代器有3个方法,分别是 hashNext(); next(); remove();,下面分别自定义实现3个方法 解释迭代器的原理。

//数组存储值
    private String [] elem = {"a","b","c"};
    //数组大小
    private int size  = elem.length;
    //定义计数器(指针 游标),在数组里面,0 代表第一个元素,-1 代表一个元素都没有
    private int courser = -1;
    //判断是否有下一个元素
    public boolean hasNext(){
        return courser+1<size;
    }
    //获取下一个元素
    public String next(){
        courser++;
        return elem[courser];
    }
   //删除某一个元素
    public void remove(){
        //数组元素的移动、其实就是数组的覆盖
        System.arraycopy(elem, courser+1, elem, courser,
                this.size-(courser+1));
        //移除了一个元素
        this.size--;
        //游标回退一位,如果游标没有往前退一步,有可能元素删除不干净list.remove();
        courser--;
    }


二,迭代器调用

上面我们将迭代器的3个基本方法分别自定义的写了一遍,我们来考虑迭代器调用的问题,如果每次调用迭代器用一个方法来封装一下 不更加方便一些,不需要重复创建对象,开辟多余的内存空间。

    //创建一个内部类,面向接口编程,使用了一个内部类
    private class MyIter implements Iterator{
    private int courser = -1;
    public boolean hasNext(){
        return courser+1<size;
    }
    public String next(){
        courser++;
        return elem[courser];
    }
    public void remove(){
        System.arraycopy(elem, courser+1, elem, courser,
                size-(courser+1));
         size--;
        courser--;
     }
    }
    //每次调用这个方法就会创建一个新的迭代器对象
    public Iterator iterator(){
        return new MyIter();
    }
  //具体调用方法
   Iterator it = list.iterater();
   while(it.hasNext()){
       System.out.println(it.next());
    }

上面的数组 是一个固定 写死了的,可不可以写一个方法,可以灵活的添加数组元素呢?

//定义一个初始元素只有5个大小的数组
private String [] elem =new String[5];
private String [] elem =new String[5];
    //大小
    private int size  = 0;
    public void add(String ele){
        //如果数组的容量超过了5,这个时候就需要扩容
        if(this.size == elem.length){//说明数组的容量不够
            elem = Arrays.copyOf(elem, elem.length+5);//自定义,想加多少就多少
        }
        elem[size] = ele;
        size++;//实际大小+1
    }

三,迭代器泛型

我们基本上了解了迭代器的一些实现原理,但是迭代器的类型也是固定的,可不可以用泛型来随意操作迭代器的类型呢?

  public class ArrayList<E> implements java.lang.Iterable<E>{
    /**
     * 使用泛型 可以操作多个类型
     */
    //泛型没有数组,所以这里使用Object来接收
    private Object [] elem =new Object[5];
    private int size  = 0;
    public void add(E ele){
        if(this.size == elem.length){
            elem = Arrays.copyOf(elem, elem.length+5);
        }
        elem[size] = ele;
        size++;//实际大小+1
    }
    
    //使用匿名内部类
    public Iterator<E>iterator(){
        return new Iterator<E>(){//Iterator迭代器接口实现类(匿名)对象
            private int courser = -1;
            public boolean hasNext(){
                return courser+1<size;
            }
            public E next(){
                courser++;
                return (E)elem[courser];
            }
            public void remove(){
                System.arraycopy(elem, courser+1, elem, courser,
                        size-(courser+1));
                 size--;
                courser--;
             }
        };//加上一个分号 表示语句的结束
    }
    public static void main(String[] args) {
        //操作Integer
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        for(Integer element:list){
            System.out.println(element);
        }
        //操作String
        ArrayList<String> listStr = new ArrayList<String>();
        listStr.add("as");
        listStr.add("asss");
        for(String str:listStr){
            System.out.println(str);
        }
    }
}

讲到迭代器,有一个接口 叫Enumberation 随便回顾一下,这个接口在jdk1.5之前用的非常的频繁,跟上文讲到的Iterator非常的类似,hasMoreElements() 判断是否有下一个元素,nextElement()获取下一个元素 案列如下:

    Vector<String> vc 
          = new Vector<String>();
    vc.add("a");
    vc.add("b");
    vc.add("c");
    Enumeration<String> en = vc.elements();
    while(en.hasMoreElements()){
        System.out.println(en.nextElement());
    }

StringTokenizer 是Enumberation的子类,实现字符串的分割,但是不支持正则表达式

String emails = 
             "cc@163.com;cc@qq.com;cc@sina.com";
    StringTokenizer str 
         = new StringTokenizer(emails,";");//只支持分隔符,不支持正则表达式
    while(str.hasMoreElements()){
        System.out.println(str.nextElement());
    }