List源码解析

原创 2015年07月08日 16:27:58
实现List接口的类
其中常用的有一个ArrayList和LinkList

1.ArrayList
ArrayList常用的方法
add(Object o)
get(int index)
remove(int index)
toArray();

不能将Object[]转换成为Arraylist[]

ArrayList的实现
任何一个集合中存放的不是对象本身,而是集合的引用
1.构造方法
 
这是ArrayList的一个构造方法,首先调用父类不带参数的构造方法
initialCapacitiy//这个值是传入构造方法的值,表示初始化的数组的长度的初始值
当这个值<0的时候抛出异常
this.elementData = new Object[initialCapacity];//这句代码表示在ArrayList的内部维护了
了一个初始值为initialCapacitiy的数组,类型为Object类型
 


这是默认不带参数的构造方法,对于不带参数的构造方法,会初始化一个EMPTY_ELEMENTDATA的数组,这是一个空数组
在旧版本的jdk中,会生成一个初始长度为10的数组



2.add方法


在add方法中调用了ensureCapacityInternal(int minCapatity)
在ensureCapacityInternal(int minCapatity)方法中elementData是ArrayList维护的一个数组
if (elementData == EMPTY_ELEMENTDATA) { //如果数组为空的时候
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);//就为数组设定一个最小值DEFAULT_CAPACITY
DEFAULT_CAPACITY是一个常量,值为10

然后再调用 ensureExplicitCapacity(int minCapacity)


  private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0) //首先判断数组中的元素是否溢出
            grow(minCapacity); //当继续往数组里面添加对象直到数组中的位置不够用的时候就会调用grow方法
    }

在数组的容量不够的时候就会调用grow方法
在这里又调用grow方法

 private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length; //首先将数组原来的长度的值赋值给oldCapacity 
        int newCapacity = oldCapacity + (oldCapacity >> 1); //(oldCapacity >> 1)这个表示右移1位,用二进制来表示就是除以2,加上原来的 oldCapacity
                                                                                               //不难得出 newCapacity的值是 oldCapacity的值的1.5倍
                                                                                               //newCapacity可以理解为预期数组的新容量,minCapacity可以理解为刚刚好包含所有元素的最小容量
        if (newCapacity - minCapacity < 0)                            //这里比较newCapacity的值和minCapacity的值                 
            newCapacity = minCapacity;                                   //如果预期容量比刚好包含所有元素的最小容量要小,预期容量就变成包含所有元素的最小容量
        if (newCapacity - MAX_ARRAY_SIZE > 0)                     //接着比较newCapacity和MAX_ARRAY_SIZE
                                                                                              //MAX_ARRAY_SIZE的值是int类型所能够表示的最大的整数值-8,java中int能够表示的最大值是2147483647
                                                                                             //所以MAX_ARRAY_SIZE的值是2147483639
            newCapacity = hugeCapacity(minCapacity);        //如果newCapacity 比 MAX_ARRAY_SIZE大,就是newCapacity的值大于2147483639,就要执行容量溢出判断
                                                                                            
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);//然后新建一个长度为newCapacity的数组u,并且将旧的elementData中原来的内容
    }                                                                                                    //复制到新的elementData中


容量溢出判断函数
 private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow                                    //如果minCapacity的值小于0,就说明数组中可以容纳的元素的个数已经超过了int类型所能够表示的范围
                                                                                                //就是超过了2147483647,为什么超过了会变成负数呢?因为在二进制中,最高位是符号位,当超过了
                                                                                                //2147483647的时候,最高位(也就是符号位)会变成1,所以变成了负数
            throw new OutOfMemoryError();                                //这时候就会抛出OutOfMemoryError();  
        return (minCapacity > MAX_ARRAY_SIZE) ?                //如果没有抛出这个错误,就会执行return语句,return语句的意思是
            Integer.MAX_VALUE :                                                //比较minCapacity 和 MAX_ARRAY_SIZE,如果是minCapacity比较大,就是所minCapacity比2147483639
            MAX_ARRAY_SIZE;                                                    //大,但是比2147483647小,这时候就返回int类型所能够表示的最大值MAX_VALUE,如果minCapacity比较小
    }                                                                                          //就返回MAX_ARRAY_SIZE,就是2147483639


3.get()方法
首先执行rangeCheck(index)方法
这个方法用来检查传入的index有没有超出元素的个数,如果超过就抛出越界异常

如果没有超过,继续执行get方法,放回elementData数组的第index个元素

4.remove()方法

 public E remove(int index) {
        rangeCheck(index);                                                                                                //首先依然是检查需要remove的元素是否有越界

        modCount++;                                                                                                          //这里的modCount的作用是对arrayList的修改次数进行计数
        E oldValue = elementData(index);                                                                           //将被删除的元素赋值到oldValue中,以便返回

        int numMoved = size - index - 1;                                                                           //计算出需要从第几个元素开始移位
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,                        //这句代码是数组拷贝,实际上是移位操作,就是从elementData的第index+1的
                             numMoved);                                                                                        //位置上开始复制到elementData的index上
        elementData[--size] = null; // clear to let GC do its work                                    //数组的size数量-1,而且最后一个元素为空

        return oldValue;
    }

LinkList的实现
1.构造方法
LinkList的实质是一个双向链表,有一个内部类,相当于节点

2.add方法
在add方法中调用了linkLast方法


 void linkLast(E e) {
        final Node<E> l = last;                                                              //将最后一个节点赋给l,这个是英文的“L”的小写不是1
        final Node<E> newNode = new Node<>(l, e, null);               //新建一个节点,新建节点的头指针为l,就是原来链表的最后一个节点
        last = newNode;                                                                        //将最后一个节点改成新的节点
        if (l == null)                                                                               //如果原来的链表是空链表,那么第一个节点就是新的节点
            first = newNode;                                                                    
        else
            l.next = newNode;                                                                //否则,原来旧的节点的最后一个节点的下一个节点就是新的节点
        size++;
        modCount++;                                                                    
    }

java集合源码解析(三)--List

今天给大家带来有序集合的接口List,我想也应该是大家在工作中用的比较多的 先来看看接口的定义: public interface List extends Collection可以看出接口Lis...

解析java.util集合类源码(List和AbstractList篇)

接口List 有序的 collection(也称为序列),作为Collection的子接口,继承了所有Collection中的方法,同时对集合进行限制 1.允许集合中的元素重复 2.提供了特殊的迭代器...

STL源码系列--List::sort算法解析

看到《STL源码剖析》中list内置sort的算法,注释说是快速排序,在网上找了快速排序的非递归实现,发现完全不同,后面网上查找,发现了下面两种比较合理的解释,记录如下。 一.解析一 转载自: ...

List接口源码解析

所在包package java.util;继承Collection接口public interface List extends Collection { // 内部代码下面讲解 }集合元素大小int...

List接口之Vector源码解析

collection接口下面有List和Set两个子接口,今天讲解一下List接口下面三个实现类Vector、LinkedList和ArrayList。 Vector:继承AbstractList,底...

《Java源码解析》集合框架List之LinkedList

LinkedList1.首先看看 LinkedList 的继承体系的结构LinkedList主要是继承自AbstractSequentialList抽象类并实现了List接口、实现了Cloneable...

List 源码解析

ListArrayList和LinkedList都继承自abstractList 都是线程不安全的。 abstractList 提供checkForComodification方法(next,add,...

《Java源码解析》集合框架List之ArrayList

Java的集合框架的底层实现在面试中用的比较多,接下来我就用一些时间来分析一下Java的集合框架中的List(ArrayList,LinkedList),Set(Set的各种实现类),Map(Hash...

python源码解析笔记--List

此文为读《python源码解剖》第四章LIST对象的笔记 List在python源码里面是PyLstObject 新创建的PyLstObject的对象如下(长度为6) 向list设置值(set)步...

LitePal和GreenDao存储list集合源码

  • 2017年10月19日 00:18
  • 34.57MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:List源码解析
举报原因:
原因补充:

(最多只允许输入30个字)