码迷,mamicode.com
首页 > 其他好文 > 详细

第二章 ArrayList源码解析

时间:2016-01-05 15:22:03      阅读:168      评论:0      收藏:0      [点我收藏+]

标签:

一、对于ArrayList需要掌握的七点内容

  • ArrayList的创建:即构造器
  • 往ArrayList中添加对象:即add(E)方法
  • 获取ArrayList中的单个对象:即get(int index)方法
  • 删除ArrayList中的对象:即remove(E)方法
  • 遍历ArrayList中的对象:即iterator,在实际中更常用的是增强型的for循环去做遍历
  • 判断对象是否存在于ArrayList中:contain(E)
  • ArrayList中对象的排序:主要取决于所采取的排序算法(以后讲)

二、源码分析

2.1、ArrayList的创建(常见的两种方式)

        List<String> strList = new ArrayList<String>();
        List<String> strList2 = new ArrayList<String>(2);

ArrayList源代码:

基本属性:

    //对象数组:ArrayList的底层数据结构
    private transient Object[] elementData;
    //elementData中已存放的元素的个数,注意:不是elementData的容量
    private int size;

构造器:

    /**
     * 创建一个容量为initialCapacity的空的(size==0)对象数组
     */
    public ArrayList(int initialCapacity) {
        super();//即父类protected AbstractList() {}
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity:" + initialCapacity);
        this.elementData = new Object[initialCapacity];
    }

    /**
     * 默认初始化一个容量为10的对象数组
     */
    public ArrayList() {
        this(10);//即上边的public ArrayList(int initialCapacity){}构造器
    }

在我们执行new ArrayList<String>()时,会调用上边的无参构造器,创造一个容量为10的对象数组。

在我们执行new ArrayList<String>(2)时,会调用上边的public ArrayList(int initialCapacity),创造一个容量为2的对象数组。

注意:

  • 上边有参构造器的super()方法是ArrayList父类AbstractList的构造方法,这个构造方法如下,是一个空构造方法:
        protected AbstractList() {
        }
  • 在实际使用中,如果我们能对所需的ArrayList的大小进行判断,有两个好处:
    • 节省内存空间(eg.我们只需要放置两个元素到数组,new ArrayList<String>(2))
    • 避免数组扩容(下边会讲)引起的效率下降(eg.我们只需要放置大约37个元素到数组,new ArrayList<String>(40))

2.2、往ArrayList中添加对象(常见的两个方法add(E)和addAll(Collection<? extends E> c))

2.2.1、add(E)

strList2.add("hello");

ArrayList源代码:

    /**
     * 向elementData中添加元素
     */
    public boolean add(E e) {
        ensureCapacity(size + 1);//确保对象数组elementData有足够的容量,可以将新加入的元素e加进去
        elementData[size++] = e;//加入新元素e,size加1
        return true;
    }
    /**
     * 确保数组的容量足够存放新加入的元素,若不够,要扩容
     */
    public void ensureCapacity(int minCapacity) {
        modCount++;
        int oldCapacity = elementData.length;//获取数组大小(即数组的容量)
        //当数组满了,又有新元素加入的时候,执行扩容逻辑
        if (minCapacity > oldCapacity) {
            Object oldData[] = elementData;
            int newCapacity = (oldCapacity * 3) / 2 + 1;//新容量为旧容量的1.5倍+1
            if (newCapacity < minCapacity)//如果扩容后的新容量还是没有传入的所需的最小容量大或等于(主要发生在addAll(Collection<? extends E> c)中)
                newCapacity = minCapacity;//新容量设为最小容量
            elementData = Arrays.copyOf(elementData, newCapacity);//复制新容量
        }
    }

在上述代码的扩容结束后,调用了Arrays.copyOf(elementData, newCapacity)方法,这个方法中:对于我们这里而言,先创建了一个新的容量为newCapacity的对象数组,然后使用System.arraycopy()方法将旧的对象数组复制到新的对象数组中去了。

2.2.2、addAll(Collection<? extends E> c)

使用方式:

        List<String> strList = new ArrayList<String>();
        strList.add("jigang");
        strList.add("nana");
        strList.add("nana2");
        
        List<String> strList2 = new ArrayList<String>(2);
        strList2.addAll(strList);

源代码:

    /**
     * 将c全部加入elementData
     */
    public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();//将c集合转化为对象数组a
        int numNew = a.length;//获取a对象数组的容量
        ensureCapacity(size + numNew);//确保对象数组elementData有足够的容量,可以将新加入的a对象数组加进去
        System.arraycopy(a, 0, elementData, size, numNew);//将对象数组a拷贝到elementData中去
        size += numNew;//重新设置elementData中已加入的元素的个数
        return numNew != 0;//若加入的是空集合则返回false
    }

注意:

  • 从上述代码可以看出,若加入的c是空集合,则返回false
  • ensureCapacity(size + numNew);这个方法在上边讲
  • System.arraycopy()方法定义如下:
    public static native void arraycopy(Object src,  int  srcPos, Object dest, int destPos,  int length);

    将数组src从下标为srcPos开始拷贝,一直拷贝length个元素到dest数组中,在dest数组中从destPos开始加入先的srcPos数组元素。

2.3、获取ArrayList中的单个对象

2.4、删除ArrayList中的对象

2.5、判断对象是否存在于ArrayList中

2.6、遍历ArrayList中的对象

三、总结

  • ArrayList基于数组方式实现,无容量的限制(会扩容)

临时有事儿,剩下的内容之后在写。

第二章 ArrayList源码解析

标签:

原文地址:http://www.cnblogs.com/java-zhao/p/5102342.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!