集合ArrayList

百般思念 提交于 2020-02-28 20:35:01

ArrayList

ArrayList 实现于 List,RanomAccess 接口。可以插入空数据,也支持随机访问

ArrayList相当于动态数据,其中最重要的两个属性分别是:elementData数组,以及size大小,在调用add()方法的时候:

public boolean add(E e){

            ensureCapactiyInternal(size +1);

            elementData[size++] =e;

            retrun true;

}

1,首先进行扩容校验

2,将插入的值放到尾部,并将size+1.

如果调用add (index ,e)在指定位置添加的话:

pubilc void add(int index ,E element){

        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);

        //复制,向后移动

        System.arraycopy(elementData, index, elementData,index +1,size-index)

        elementData[index] =element;

        size++;

}

1,也是首先扩容校验

2,接着对数据进行复制,目的是把index位置空出来放本次插入的数据,并将后面的数据

向后移动一个位置

其实扩容最终调用的代码:

private  void  grow(int minCapacity){

        int oldCapactiy =elementData.length;

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

        if(newCapcity -minCapacity <0)

                newCapcity=minCapacity ;

        if(newCapcity-MAX_ARRAY_SIZE >0)

                newCapcity=hugeCapacity(minCapacity);

        elementData =Arrays.copyOf(elementData ,newCapacity);       

}

也是一个数组复制的过程

由此可见ArrayList的主要消耗是数组扩容以及在指定位置添加数据,在日常使用时最好是指定大小,尽量减少扩容,

更要减少在指定位置插入数据的操作

序列化

由于ArrayList是基于动态数组实现的,所以并不是所有的空间都被使用,因此transient修饰,可以防止被自动序列化

        transient Object[] elementData;

因此ArrayList自定义了序列化和反序列化:

        private  void  writeObject(java.io.ObjectOutputStream s)

        throws java.io.IOException{

        int expectedModCount =modCount;

        s.defalutWriteObject();

        s.writeInt(size);

        //只序列化了被使用的数据

        for(int i =0; i<size ; i++){

        s.writeObject(elementData[i]);

        }

         if(modCount != exceptedModCount){

            throw new ConcurrentModifacationException();

        }

}

    private  void readObject(java.io.ObjectInputStream s)

            throw java.io.IOException ,ClassNotFoundException{

             elementData =EMPTY_ELEMENTDATA;

            s.defaultReadObject();

            s.readInt();

            if(size >0){

            ensureCapacityInternal(size);

            Object[]  a=elementData;

            for(int i=0; i<size;  i++){

                a[i]=s.readObject();

                }

            }

}

当对象中自定义了writeObject和readObject方法时,JVM会调用这两个自定义方法来实现序列化和反序列化

所以从实现中可以看出ArrayList只序列化了被使用的数据

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!