集合(一)ArrayList

ArrayList底层是用数组实现的存储。
查询的效率高,增删效率低,线程不安全。

属性及构造方法
    // 默认容量
    private static final int DEFAULT_CAPACITY = 10;
    // 空数组
    private static final Object[] EMPTY_ELEMENTDATA = {};
    // 空数组
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    // 未初始化的空数组 
    transient Object[] elementData; // non-private to simplify nested class access
    // 容量大小
    private int size;

    /**
     * ArrayList指定长度构造方法
     */
    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);
        }
    }

    /**
     * Constructs an empty list with an initial capacity of ten.
     * 无参构造方法
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    /**
    * 参数为Collection对象的构造方法
    */
  public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

当我们使用无参的构造方法时,会给elementData赋值一个空数组,容量大小是0,并不是注释上说的10,真正意义上分配大小的时候,是执行add()方法的时候。为什么注释会写分配了10呢,因为JDK1.7以前初始化的时候默认会调this(10),分配容量,忘记改了吧。

常用方法
add()方法 扩容机制
    /**
     * 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) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

在这里插入图片描述

remove()方法在这里插入代码片

remove方法和add方法很类似,也是采用数组copy的方法,将指定下标后一位到数组末尾的全部元素向前移一位。然后把最后一个元素设置为null。容量保持不变。

set()方法

set(int index, E element)方法的作用是指定下标索引处的元素的值。在ArrayList的源码实现中,方法内首先判断传递的元素数组下标参数是否合法,然后将原来的值取出,设置为新的值,将旧值作为返回值返回。

ArrayList<Integer> list = new ArrayList<Integer>();
list.set(0,0);

这样子使用会报错,原因如下

    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

线程安全性

因为在add()方法的时候,在index位置添加元素,和size++并不是原子性的,分成了添加元素和size++ 两个步骤。
假设有一个ArrayList,size = 1,此时有两个线程对他操作,第一个线程已经把元素添加到ArrayList的第二个位置上进去了,但是还没有执行size++操作,此时另一个线程进来添加元素,由于现在的size还是1,添加的位置还是第二个。然后两个线程再执行size++操作,而实际上ArrayList只有一个元素,所以ArrayList线程不安全。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值