zoukankan      html  css  js  c++  java
  • java中ArrayList 遍历方式、默认容量、扩容机制

     

    遍历

    先定义ArrayList,并填充数据

                    //定义集合
            ArrayList arr = new ArrayList<>();
            //添加数据
            for(int i = 0; i < 10; i ++) {
                arr.add(i);
            }        

    1、下标遍历

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

    2、foreEach (jdk 1.5 及以上可用)

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

    3、java 8 新特性 Lambda表达式 (jdk 1.8 及其以上)

    arr.forEach(x -> System.out.println(x));

    4、Iteraotr迭代器

    Iterator iterator = arr.iterator();
    while(iterator.hasNext()) {
        System.out.println(iterator.next());
    }

    5、ListIterator 迭代器 (这个是List集合特有的)

    //List转用迭代
    ListIterator listIterator = arr.listIterator();
    //从前往后
    System.out.println("listIterator 从前往后 ");
    while(listIterator.hasNext()) {
        System.out.println(listIterator.next());
    }
    
    //从后往前
    System.out.println("listIterator 从后往前 ");
    while(listIterator.hasPrevious()) {
        System.out.println(listIterator.previous());
    }

    默认容量,和扩容机制

    默认容量为10,有图有真相:

    扩容机制,先看一下扩容的源代码吧:

        //minCapacity 代表着最小扩容量
        private void grow(int minCapacity) {
            // overflow-conscious code
            //elementData 是 ArrayList存储数据的数组 这里是获取当前数组的长度
            int oldCapacity = elementData.length;
            //计算扩容后的数组长度 = 当前数组长度  + (当前数组长度 * 0.5) ;也就是扩容到当前的 1.5 倍
            int newCapacity = oldCapacity + (oldCapacity >> 1);
            //判断新的数组是否满足最小扩容量,如果不满足就将新数组的扩容长度赋值为最小扩容量
            if (newCapacity - minCapacity < 0)
                newCapacity = minCapacity;
            if (newCapacity - MAX_ARRAY_SIZE > 0)
                newCapacity = hugeCapacity(minCapacity);
            // minCapacity is usually close to size, so this is a win:
            elementData = Arrays.copyOf(elementData, newCapacity);
        }

    恩,也就是说ArrayList通常的套路是当容量不足时就扩容到当前容量的 1.5被。下面我通过java反射机制证明这一点:

    public static void main(String[] args) throws Exception {
            ArrayList a = new ArrayList<>();
            for (int i = 0; i < 30; i++) {
                a.add(i);
                print(a);
            }
        }
        static void print(List list) throws Exception {
            Class c = list.getClass();
            //elementData 就是ArrayList用于底层存储数据的数组,
            //我们通过观察数组长度的变化来证明我们所说的扩容机制正确性
            Field  f = c.getDeclaredField("elementData");
            //设置可访问
            f.setAccessible(true);
            //反射对象
            Object[] elementData = (Object[])f.get(list);
            System.out.println("elementData.length" + elementData.length + ",size" + list.size());
        }

    下面时执行结果:

    elementData.length10,size1
    elementData.length10,size2
    elementData.length10,size3
    elementData.length10,size4
    elementData.length10,size5
    elementData.length10,size6
    elementData.length10,size7
    elementData.length10,size8
    elementData.length10,size9
    elementData.length10,size10
    elementData.length15,size11
    elementData.length15,size12
    elementData.length15,size13
    elementData.length15,size14
    elementData.length15,size15
    elementData.length22,size16
    elementData.length22,size17
    elementData.length22,size18
    elementData.length22,size19
    elementData.length22,size20
    elementData.length22,size21
    elementData.length22,size22
    elementData.length33,size23
    elementData.length33,size24
    elementData.length33,size25
    elementData.length33,size26
    elementData.length33,size27
    elementData.length33,size28
    elementData.length33,size29
    elementData.length33,size30

    ArrayList扩容是向上取整还是向下取整?

    int newCapacity = oldCapacity + (oldCapacity >> 1);

    oldCapacity >> 1 就是 oldCapacity * 0.5 jdk人员将它设计成这样是为了更高的效率。记住  oldCapacity >> 1 是向下取整 。

     

  • 相关阅读:
    javaScript -- touch事件详解(touchstart、touchmove和touchend)
    PHP 报错--Array to string conversion,请用print_r() 来输出数组
    PHP微信商户支付
    解决问题:CA_ERROR证书出错,请登录微信支付商户平台下载证书-企业付款到零钱接口(原创)
    写毕业设计论文或写书关于参考文献的一些原则
    分享腾讯云的Linux服务器连接速度很慢的解决心得(原创)
    Linux 实时性能测试工具——Cyclictest【转】
    Linux Kernel中获取当前目录方法(undone)【转】
    Linux kernel 绝对路径之d_path篇【转】
    linux内核获取进程的全路径3种方法【转】
  • 原文地址:https://www.cnblogs.com/IT-CPC/p/10886007.html
Copyright © 2011-2022 走看看