java ArrayList 详解

java ArrayList 详解

img

什么是arrayList ?

​ 简单讲就是动态数组,容量不固定无需指定数组大小;

特点:

  1. 既然说是动态数组,那肯定跟数组脱不了关系 底层由数组构成
  2. 容量不固定,有最大阈值,默认初始化为10
  3. 底层是数组 查询类方法效率极高(size,isEmpty,get…)
  4. 线程不安全

重要方法:

add:

​ 下图中两个方法,一个是直接添加一个元素值,另一个是在指定的位置添加一个元素,操作比较简单都是调用了一个 ensureCapacityInternal方法,然后进行数组赋值,主要的步骤就是在这个方法中,其中扩容相关的都在这里边;

 public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

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

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

在上述方法中会有一个判断如果容量不够了就调用 grow()方法来进行扩容,其容量是原先的1.5倍,1.8版本采用的是位运算,相当于除以2,效率变高了\

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        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);
    }

romove:

注意一点当数组进行数据删除的时候只是将元素删除,数组的长度并不会进行缩容,也就是说只有扩容没有缩容

根据位置

public E remove(int index) {
// 检查越界
rangeCheck(index);
modCount++;
// 需要移除的元素
E oldValue = elementData(index);
// 需要移动位置的元素的数量
int numMoved = size - index - 1;
// 将需要移除元素的位置后的所有元素复制到index位置开始后的numMoved个位置
if (numMoved > 0)
    System.arraycopy(elementData, index+1, elementData, index,
                     numMoved);
// size减1,并将之前的最后一个位置元素置空
elementData[--size] = null; // clear to let GC do its work
return oldValue;

根据值

public boolean remove(Object o) {
    if (o == null) {
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) {
                fastRemove(index);
                return true;
            }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;
}

线程不安全

面试中我们经常会被问到arrayList 线程安全吗?答案是不安全的,

原因有下面几点:

  1. 扩容,当进行扩容的时候 如果有两个线程同时来进行add 操作 并且到扩容的阶段的话,会出现数组越界,就是当一个线程拿到另一个线程扩容后的size 值的时候

  2. 另一个是在赋值的阶段两个线程同时进行会造成数据覆盖

    具体的操作可以参考一下这个:https://blog.csdn.net/u012859681/article/details/78206494

造成数据覆盖

具体的操作可以参考一下这个:https://blog.csdn.net/u012859681/article/details/78206494

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值