首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java容器源码攻坚战--第一战:Iterator

Java容器源码攻坚战--第一战:Iterator

作者头像
张风捷特烈
发布2018-10-08 10:26:08
3600
发布2018-10-08 10:26:08
举报

基于java10.1

零、前言

如果想读读源码测试功力,或读读源码修养身心,或读读源码满足自虐倾向,我建议第一个类是:ArrayList 第一、常用----所以用法比较熟悉,看完源码你也会更明白如何去用 第二、相对简单----1595行代码,刨去注释的一大堆也没有太多,还是hold的住的 第三、还没想好

这篇并不是讲ArrayList,而是Iterator,它是容器以及映射中非常重要的一环

一、迭代器模式

提起设计模式,总是有种只知其形,难达其意的感觉,用三个字说就是高大上

迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。

优势:  它支持以不同的方式遍历一个聚合
        迭代器简化了聚合的接口
        在同一个聚合上可以有多个遍历

迭代器模式.png

1.适配器接口

最简单的适配器有两个方法hasNext()和next(),这两个方法可以组成一个逻辑链:如果有下一个,取出下一个

/**
 * 作者:张风捷特烈
 * 时间:2018/10/1 0001:23:11
 * 邮箱:1981462002@qq.com
 * 说明:适配器接口
 */
public interface Iterator<T> {
    /**
     * 是否有下一个元素
     * @return 是否有下一个元素
     */
    boolean hasNext();

    /**
     * 下一个元素
     * @return 下一个元素
     */
    T next();
}
2.聚合对象接口

所谓聚合就是内部含有多个某类型的元素,比如教室和学生的关系,就是聚合对象(教室)与单体元素(学生)的关系

/**
 * 作者:张风捷特烈
 * 时间:2018/10/1 0001:23:17
 * 邮箱:1981462002@qq.com
 * 说明:聚合对象接口
 */
public interface Group<T> {
    /**
     * 添加元素
     * @param el 元素
     */
    void add(T el);

    /**
     * 获取元素
     * @param index 索引
     * @return 元素
     */ 
    T get(int index);

    /**
     * 获取迭代器
     * @return 迭代器
     */
    Iterator<T> iterator();

    /**
     * 内部元素总数
     * @return 元素总数
     */
    int size();
}
3.迭代器实现类
/**
 * 作者:张风捷特烈
 * 时间:2018/10/1 0001:23:13
 * 邮箱:1981462002@qq.com
 * 说明:迭代器实现类
 */
public class IteratorImpl<T> implements Iterator {
    //持有聚合对象引用
    private Group<T> mGroup;
    //当前游标指向的索引处
    private int curIndex;

    public IteratorImpl(Group group) {
        mGroup = group;
    }

    @Override
    public boolean hasNext() {
        //当游标的指向索引比元素总数少,说明还有next
        return curIndex < mGroup.size();
    }

    @Override
    public T next() {
        //返回当前索引处元素
        T el = mGroup.get(curIndex);
        //当游标的指向索引后移
        curIndex++;
        return el;
    }
}
4.集合对象实现类
/**
 * 作者:张风捷特烈
 * 时间:2018/10/1 0001:23:20
 * 邮箱:1981462002@qq.com
 * 说明:集合对象实现类
 */
public class GroupImpl<T> implements Group<T> {
    //维护一个数组盛放元素
    private T[] data;
    //维护内部元素个数
    private int size = 0;

    public GroupImpl() {
        //为了简单,使用固定容积50
        data = (T[]) new Object[50];
    }

    @Override
    public void add(T el) {
        data[size] = el;
        size++;
    }

    @Override
    public T get(int index) {
        return data[index];
    }

    @Override
    public Iterator<T> iterator() {
        return new IteratorImpl(this);
    }

    @Override
    public int size() {
        return size;
    }
}
5.测试
public class Client {
    public static void main(String[] args) {
        GroupImpl<Student> classRoom = new GroupImpl<>();
        classRoom.add(new Student(1, "捷特"));
        classRoom.add(new Student(2, "龙少"));
        classRoom.add(new Student(3, "巫缨"));

        for (int i = 0; i < classRoom.size(); i++) {
            System.out.println(classRoom.get(i));
        }

        Iterator<Student> it = classRoom.iterator();
//        System.out.println(it.next());//Student{id=1, name='捷特'}
//        System.out.println(it.next());//Student{id=2, name='龙少'}
//        System.out.println(it.next());//Student{id=3, name='巫缨'}
//        System.out.println(it.next());//null
        
        while (it.hasNext()) {
            System.out.println(it.next());
//            Student{id=1, name='捷特'}
//            Student{id=2, name='龙少'}
//            Student{id=3, name='巫缨'}
        }
    }
}

迭代器模式例.png


二、ArrayList中的Iterator

java中内置的聚合类,顶尖接口Collection实现了Iterable接口,也就是可迭代

1.Iterable接口中定义了获取Iterator对象的函数iterator()
public interface Iterable<T> {
    Iterator<T> iterator();
2.Collection继承了Iterable接口也必然继承它的方法
public interface Collection<E> extends Iterable<E> {
    Iterator<E> iterator();
3.同样List接口继承了Collection接口也必然这个方法
public interface List<E> extends Collection<E> {
    Iterator<E> iterator();
4.java中自带的迭代器:Iterator
public interface Iterator<E> {
    //是否拥有下一个元素
    boolean hasNext();
    //下一个元素
    E next();

    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}
4.该方法在ArrayList中的实现

private class Itr implements Iterator<E>说明该迭代器实现类Itr是ArrayList的内部类 这样做就不必让Itr持有ArrayList的引用,简单一些。

    public Iterator<E> iterator() {
        //返回一个迭代器实现类对象
        return new Itr();
    }

    private class Itr implements Iterator<E> {
        int cursor;       // 游标:将要返回的元素索引
        int lastRet = -1; // 最后一个被返回元素的索引,-1表示没有返回过
        int expectedModCount = modCount;//期望的修改次数与真是修改次数置同

       //私有化构造方法
        Itr() {}

        public boolean hasNext() {
            //当游标未达到元素总数时,表明还有下一个元素
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();//见I--1
            int i = cursor;//用变量i暂存游标位置
            if (i >= size)//游标位置大于等于size,抛出异常
                throw new NoSuchElementException();
            //获取当前ArrayList的成员变量:elementData(当前数组)
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)//游标位置大于当前数组总长,抛出异常
                throw new ConcurrentModificationException();
            cursor = i + 1;//游标后移
            //维护lastRet为i,即返回的元素索引
            return (E) elementData[lastRet = i];
        }

        public void remove() {
            if (lastRet < 0)//即没有调用过next()方法:见Test-1
                throw new IllegalStateException();
            checkForComodification();//见I--1
            try {
                ArrayList.this.remove(lastRet);//移除操作
                cursor = lastRet;//索引指向刚才移除的索引位
                lastRet = -1;//最后返回的索引置为-1,[由此可见不能连续执行两次iterator.remove()操作]
                expectedModCount = modCount;//期望的修改次数与真是修改次数置同
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        @Override//测试见:Test-2
        public void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);//判断是否为空,空则抛空指针
            final int size = ArrayList.this.size;//size记录元素中个数
            int i = cursor;//用变量i暂存游标位置
            if (i < size) {
                final Object[] es = elementData;//记录数组
                if (i >= es.length)//越界
                    throw new ConcurrentModificationException();
                for (; i < size && modCount == expectedModCount; i++)
                    action.accept(elementAt(es, i));//见I--2
                // update once at end to reduce heap write traffic
                cursor = i;
                lastRet = i - 1;
                checkForComodification();///见I--1
            }
        }
    }

I--1:查看期望修改次数与实际修改次数是否相同
final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}

I--2:返回一个数组指定索引位置的元素
   static <E> E elementAt(Object[] es, int index) {
        return (E) es[index];
    }

Test-1
        ArrayList<String> aList = new ArrayList();
        aList.add("b");
        aList.add("a");
        aList.add("c");
        
        Iterator<String> iterator = aList.iterator();
        iterator.remove();//直接使用移除会报异常
        //Exception in thread "main" java.lang.IllegalStateException
        ArrayList<String> aList = new ArrayList();
        aList.add("b");
        aList.add("a");
        aList.add("c");

        Iterator<String> iterator = aList.iterator();
        String first = iterator.next();
        System.out.println(first);//b
        System.out.println(aList);//[b, a, c]
        //执行过iterator.next(),lastRet指向返回元素的位置,就不再是0,调用remove就不会异常了
        iterator.remove();//移除iterator最后返回的元素
        System.out.println(aList);//[a, c]
        Iterator<String> iterator = aList.iterator();
        String first = iterator.next();
        String second = iterator.next();
        System.out.println(first);//b
        System.out.println(second);//a
        System.out.println(aList);//[b, a, c]
        //执行两次iterator.next(),iterator最后返回的元素为a,移除之
        iterator.remove();
        System.out.println(aList);//[b, c]

Test-2
ArrayList<String> aList = new ArrayList();
aList.add("b");
aList.add("a");
aList.add("c");
Iterator<String> iterator = aList.iterator();

iterator.forEachRemaining(s -> {
    s += "-Hello";
    System.out.print(s+" ");//b-Hello a-Hello c-Hello 
});

就酱紫,Iterator这个类的用法差不多也就这些


后记:捷文规范
1.本文成长记录及勘误表

项目源码

日期

备注

V0.1--无

2018-10-2

Java容器源码攻坚战--第一战:Iterator

V0.2--无

-

-

2.更多关于我

笔名

QQ

微信

爱好

张风捷特烈

1981462002

zdl1994328

语言

我的github

我的简书

我的CSDN

个人网站

3.声明

1----本文由张风捷特烈原创,转载请注明 2----欢迎广大编程爱好者共同交流 3---个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正 4----看到这里,我在此感谢你的喜欢与支持

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.10.02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 零、前言
  • 一、迭代器模式
    • 1.适配器接口
      • 2.聚合对象接口
        • 3.迭代器实现类
          • 4.集合对象实现类
            • 5.测试
            • 二、ArrayList中的Iterator
              • 1.Iterable接口中定义了获取Iterator对象的函数iterator()
                • 2.Collection继承了Iterable接口也必然继承它的方法
                  • 3.同样List接口继承了Collection接口也必然这个方法
                    • 4.java中自带的迭代器:Iterator
                      • 4.该方法在ArrayList中的实现
                        • I--1:查看期望修改次数与实际修改次数是否相同
                        • I--2:返回一个数组指定索引位置的元素
                        • Test-1
                        • Test-2
                    • 后记:捷文规范
                      • 1.本文成长记录及勘误表
                        • 2.更多关于我
                          • 3.声明
                          相关产品与服务
                          容器服务
                          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                          领券
                          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档