zoukankan      html  css  js  c++  java
  • ArrayList读源码心得

      首先给一个ArrayList和LinkedList速度方面的比较

            ArrayList  LinkedList

        增加:    慢      快

        删除:    慢      快

        修改:    快      快

        查询:    快      慢

    如果认真阅读LinkedList算法详解就能对LinkedList各方面速度应该有所了解

    下面对ArrayList的操作总体介绍,ArrayList所有操作都是建立在他内部封装的一个Object[]数组以及size:

        /**
         * The array buffer into which the elements of the ArrayList are stored.
         * The capacity of the ArrayList is the length of this array buffer.
         */
        private transient Object[] elementData;
    
        /**
         * The size of the ArrayList (the number of elements it contains).
         *
         * @serial
         */
        private int size;

    这是源码,下面看一下ArrayList的构造函数:

        /**
         * Constructs an empty list with the specified initial capacity.
         *
         * @param   initialCapacity   the initial capacity of the list
         * @exception IllegalArgumentException if the specified initial capacity
         *            is negative
         */
        public ArrayList(int initialCapacity) {
        super();
            if (initialCapacity < 0)
                throw new IllegalArgumentException("Illegal Capacity: "+
                                                   initialCapacity);
        this.elementData = new Object[initialCapacity];
        }

    这是ArrayLis一个带参数的函数,代表默认加载大小,不能小于0。如果有大数据,添加最好初始化一个比较大的数字,因为ArrayList每次添加都会判断容量够不够,如果不够他就会自动增加为:size/2*3+1也就是增加二分之一,而且还进行copy操作所以首先给一个容量,对性能提升应该很有帮组。

        /**
         * Increases the capacity of this <tt>ArrayList</tt> instance, if
         * necessary, to ensure that it can hold at least the number of elements
         * specified by the minimum capacity argument.
         *
         * @param   minCapacity   the desired minimum capacity
         */
        public void ensureCapacity(int minCapacity) {
        modCount++;
        int oldCapacity = elementData.length;//取到实际长度
            //判断大于实际
        if (minCapacity > oldCapacity) {
            Object oldData[] = elementData;
            int newCapacity = (oldCapacity * 3)/2 + 1;
                if (newCapacity < minCapacity)
            newCapacity = minCapacity;
                //创建一个新长度的数组
                elementData = Arrays.copyOf(elementData, newCapacity);
        }
        }    

    添加操作:

        /**
         * Appends the specified element to the end of this list.
         *
         * @param e element to be appended to this list
         * @return <tt>true</tt> (as specified by {@link Collection#add})
         */
        public boolean add(E e) {
        ensureCapacity(size + 1);  // 判断下一个数组的length是否有容量
        elementData[size++] = e;
        return true;
        }

    看到Add应该就能了解速度慢在什么地方:每次添加都判断长度是否达到,如果没有就行下Array.copy(elements,length);操作,该操作可想而知他的速度。

    删除操作:

        public E remove(int index) {
        RangeCheck(index);//检查索引是否>=size,如果大于抛出异常
    
        modCount++;//这里不讲解,如果需要了解请自行看源码。防止迭代修改和多线程迭代修改
        E oldValue = (E) elementData[index];//返回值
    
        int numMoved = size - index - 1;//取后半截的长度
            //大于0就执行数组copy操作
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                     numMoved);
        elementData[--size] = null; //最后一个为空
    
        return oldValue;
        }

    其中有句没注释:System.arraycopy(elementData, index+1, elementData, index, numMoved);这也是关键操作,这个方法的作用是:

      把index+1(包括index+1)后面的元素,赋值到index(包括index)后面,index就直接被覆盖。numMoved截取大长度。

    修改操作:

        public E set(int index, E element) {
        RangeCheck(index);
    
        E oldValue = (E) elementData[index];
        elementData[index] = element;
        return oldValue;
        }

    修改也是非常快速的。

    查询操作:

        public E get(int index) {
        RangeCheck(index);
    
        return (E) elementData[index];
        }

    只接根据根据index查询,数组查询时非常快速的。

    这是我实现的MyArrayList:

    package servlet;
    import java.util.AbstractList;
    import java.util.Arrays;
    import java.util.Collection;
    import java.util.List;
    @SuppressWarnings("unchecked")
    public class MyArrayList<T> extends AbstractList<T> implements List<T> {
    
        private Object[] elements;
    
        private int size; //reality
    
        public int size() {
    
            return size;
        }
        
        
        public MyArrayList(){
            elements=new Object[10];
        }
        
        /*
         * by index modify to t(non-Javadoc)
         * @see java.util.AbstractList#set(int, java.lang.Object)
         */
        public T set(int index,T t){
            rangeCheck(index);
            elements[index]=t;
            return t;
        }
        
        /*
         * by index return elements[index]
         * 
         * @see java.util.AbstractList#get(int)
         */
        public T get(int index) {
            if (index >= size)
                throw new IndexOutOfBoundsException("index:" + index + ",size:"
                        + size);
            return (T) elements[index];
        }
        
    
        /*
         * this list is null
         * 
         * @see java.util.AbstractCollection#isEmpty()
         */
        public boolean isEmpty() {
    
            return size == 0;
        }
    
        
        /*
         * to Array(non-Javadoc)
         * 
         * @see java.util.AbstractCollection#toArray()
         */
        public Object[] toArray() {
            return Arrays.copyOf(elements, size);
        }
    
        
        /*
         * load a to ArrayList
         * 
         * @see java.util.AbstractCollection#toArray(T[])
         */
        
        @SuppressWarnings("hiding")
        public <T> T[] toArray(T[] a) {
            if (a.length > size)
                System.arraycopy(elements, 0, a, 0, elements.length);
            else
                System.arraycopy(elements, 0, a, 0, a.length);
            return a;
        }
    
        
        /*
         * add element(non-Javadoc)
         * @see java.util.AbstractList#add(java.lang.Object)
         */
        public boolean add(T e) {
            ensureCapcity(size+1);
            elements[size++] = e;
            return true;
        }
        
        
        /*
         * add by index
         */
        public void add(int index,T e){
            if(index < 0 || index>size){
                throw new IndexOutOfBoundsException("index:"+index+" ?");
            }
            Object[] obj=Arrays.copyOf(elements, ++size);
            elements=obj;
            System.arraycopy(elements, index, elements, index+1, size-index-1);//数组前移
            elements[index]=e;
        }
        
        
        /*
         * by o remove
         * 
         * @see java.util.AbstractCollection#remove(java.lang.Object)
         */
        public boolean remove(Object o) {
            if (o != null) {
                for (int index = 0; index < elements.length; index++) {
                    if (o.equals(elements[index])) {
                        faceRemove(index);
                        return true;
                    }
                }
            } else {
                for (int index = 0; index < elements.length; index++) {
                    if (o == (elements[index])) {
                        faceRemove(index);
                        return true;
                    }
                }
            }
            return false;
        }
        
    
        /**
         * remove
         */
        public void faceRemove(int index) {
            rangeCheck(index);
            if (index < size) {
                System.arraycopy(elements, index + 1, elements, index, --size - index);//后移
                elements[size] = null;
            }
    
        }
        
        
        /*
         * amalgamate collection(non-Javadoc)
         * @see java.util.AbstractCollection#addAll(java.util.Collection)
         */
        public boolean addAll(Collection<? extends T> c) {
            Object[] obj = c.toArray();
            int temp=c.size()+size;
            ensureCapcity(temp);
            System.arraycopy(obj, 0, elements, size, c.size());
            size=temp;
            return true;
        }
        
        
        /*
         * clear(non-Javadoc)
         * @see java.util.AbstractList#clear()
         */
        public void clear() {
            for(int i=0;i<size;i++){
                elements[i] = null;
            }
            size=0;
        }
        
        /*
         * by object query index(non-Javadoc)
         * @see java.util.AbstractList#indexOf(java.lang.Object)
         */
        public int indexOf(Object o) {
            if (o == null)
                for (int index = 0; index < size; index++) {
                    if (elements[index] == null) {
                        return index;
                    }
                }
            else
                for (int index = 0; index < size; index++) {
                    if (elements[index].equals(o)) {
                        return index;
                    }
                }
            return -1;
        }
        
        public T remove(int index){
            T temp=(T) elements[index];
            faceRemove(index);
            return temp;
        }
        
        /**
         * 扩充容量
         * 
         * @Author :sheyong
         */
        private void ensureCapcity(int length) {
            if (length > elements.length) {
                int temp = size * 3 / 2+1;
                if (temp < length) {
                    temp=length;
                }
                elements = Arrays.copyOf(elements, temp);
            }
        }
        
        /** 
         * @Author : sheyong
         */
        public void rangeCheck(int index){
            if(index<0 || index>=size){
                throw new IndexOutOfBoundsException("index:" +index+" ?");
            }
        }
    }

    源码下载

    ArrayList里面所有操作都是基于System.arraycopy方法,这个方法底层是jni,c++实现,因为c++对数组操作速度快。

    未完待续。。。

  • 相关阅读:
    .NET 4.0 System.Threading.Tasks学习笔记
    c#初学-多线程中lock用法的经典实例
    Spring3 Schedule Task之注解实现 (两次起动Schedule Task 的解决方案)
    支持向量机中的函数距离的理解
    Sqlserver 2016 R Service环境安装的各种错误(坑)解决办法
    Sql server的Merge语句,源表中如果有重复数据会导致执行报错
    对IIS7经典模式和集成模式的理解(转载)
    VisualStudio编译项目时,提示bin目录和obj目录下的文件不能写的错误处理的解决办法
    SQL Server 全文索引介绍(转载)
    sql server全文索引使用中的小坑 (转载)
  • 原文地址:https://www.cnblogs.com/JimmyXie/p/2881472.html
Copyright © 2011-2022 走看看