美文网首页
Java 集合 — ArrayList 分析

Java 集合 — ArrayList 分析

作者: 波波维奇c | 来源:发表于2018-04-21 17:06 被阅读0次
    List 集合的特征:
    • 有序
    • 可以重复
    • 可以随机访问(使用下标 添加,删除,访问)
    ArrayList 是 List 的实现类,所以 ArrayList 具有 List 的特征
    • ArrayList 是非线程安全的 (非同步)
    线程安全,非安全的定义:
    • 线程安全(同步):
      当多线程访问时,采用加锁的机制;即当一个线程访问该类的某个数据的时候,会对这个数据进行保护,使其他线程不能对其访问,直到该线程读取完,其他线程之后才可使用,防止出现数据不一致或数据被污染的情况。

    • 线程不安全(非同步):
      没有提供数据访问时的数据保护,多个线程能操作同一个数据。

    底层分析:

    点击 ArrayList 进来可以发现,他是由一个 数组类型来保存数据的,所以它支持 数组 的操作。

    transient Object[] elementData; // non-private to simplify nested class access
    
    构造方法:

    第一个构造方法,会初始化一个空列表

    privat staic final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = { };
    ...省略代码
    public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    
    public void ensureCapacity(int minCapacity) {
    //在这里判断,如果初始化时是否空列表,是就分配系统默认的 DEFAULT_CAPACITY  =10
    int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
    // any size if not default element table
    ? 0
    // larger than default for default empty table. It's already
    // supposed to be at default size.
    : DEFAULT_CAPACITY;
    //这里判断如果,我们通过设置 ensureCapacity() 来增加容量
    //就会判断我们设置的容量和默认容量的判断
    if (minCapacity > minExpand) {
    ensureExplicitCapacity(minCapacity);
        }
    }
    //继续跟进
    private void ensureExplicitCapacity(int minCapacity) {
    modCount++;
    // overflow-conscious code
    //在这里判断 如果我们增加的容量比默认容量大时(也就是容量不够时),数组就回去扩容
    if (minCapacity - elementData.length > 0)
    grow(minCapacity);
    }
    //继续跟进
    private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);//扩容的容量为原来的1.5倍
    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);//拷贝复制到扩容后的数组
    }
    

    第二构造方法

    是创建一个给定大小容量的数组,然后判断给定的容量符不符合
    public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
    this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
       this.elementData = EMPTY_ELEMENTDATA;
    } else {
    throw new IllegalArgumentException("Illegal Capacity: "+
    initialCapacity);
      }
    }
    

    第三方构造方法

    由注释可以知道, 构造一个包含指定collection的元素的列表,这些元素按照该collection的迭代器返回它们的顺序排列的
    
    /**
    * Constructs a list containing the elements of the specified
    * collection, in the order they are returned by the collection's
    * iterator.
    *
    * @param c the collection whose elements are to be placed into this list
    * @throws NullPointerException if the specified collection is null
    */
    public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
    // c.toArray might (incorrectly) not return Object[] (see 6260652)
    // 当c.toArray返回的不是object类型的数组时,进行下面转化。
    if (elementData.getClass() != Object[].class)
    elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
    // replace with empty array.
    this.elementData = EMPTY_ELEMENTDATA;
    }
    }
    

    add 方法

    //添加元素到列表的尾部,然后给容量和数组大小都加1
    public boolean add(E e) {
    ensureCapacityInternal(size + 1); // Increments modCount!!
    elementData[size++] = e;
    return true;
    }
    //进行跟进
    private void ensureCapacityInternal(int minCapacity) {
    //这里是 在增加元素的时候,如果列表一开始是空列表,就在 add 之后,就会去取添加的元素容量和默认值间中的最大值
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
    minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    //这个方法就是刚才上面分析第一个构造函数的时候,在容量不够时,就去扩容
    ensureExplicitCapacity(minCapacity);
    }
    
    
    
    //添加知道位置的元素
    public void add(int index, E element) {
    //判断添加的元素位置是否合理
    if (index > size || index < 0)
    throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    
    ensureCapacityInternal(size + 1); // Increments modCount!!
    //从 elementData 在 index 位置开始将 size -index 个数从 elementData 的 index+1的位置开始存放
    //也就是从 index 这个开始之后位置都 +1
    System.arraycopy(elementData, index, elementData, index + 1,
    size - index);
    elementData[index] = element;
    size++;
    }
    

    addAll

    public boolean addAll(Collection<? extends E> c) {
    Object[] a = c.toArray();   //转为数组
    int numNew = a.length;
    ensureCapacityInternal(size + numNew); //和上面一样,只是加的大小不一样
    //a 数组 从 0 位置开始复制 numNew 的个数到 elementData中,从 size 的位置开始存放
    System.arraycopy(a, 0, elementData, size, numNew);
    size += numNew;
    return numNew != 0;
    }
    
    
    
    public boolean addAll(int index, Collection<? extends E> c) {
    if (index > size || index < 0)
    throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    
    Object[] a = c.toArray();
    int numNew = a.length;
    ensureCapacityInternal(size + numNew); //和上面一样,只是加的大小不一样
    
    int numMoved = size - index;
    if (numMoved > 0)
    // 数组 elementData 从位置 index 开始 复制 numMoved 个数到 elementData 的index+numNew开始存放
    System.arraycopy(elementData, index, elementData, index + numNew,
    numMoved);
    
    System.arraycopy(a, 0, elementData, index, numNew);
    size += numNew;
    return numNew != 0;
    }
    
    

    其他的一些 get,set, remove 方法,思路和上面一样知道 增加 和 移除后 一些元素的位置要进行改变,就不列出代码了。

    相关文章

      网友评论

          本文标题:Java 集合 — ArrayList 分析

          本文链接:https://www.haomeiwen.com/subject/ukoxlftx.html