java数组底层原理是什么?Java底层之ArrayList底层实现原理

阳光 2021-08-20 17:58:47 java常见问答 8535

其实数组就是一个容器,可以自动给数组中的元素从0开始编号,方便操作这些元素。那java数组底层原理是什么?下面来我们就来给大家讲解一下Java底层之ArrayList底层实现原理。

ArrayList就是动态数组,相当于Array的复杂版本,它提供了动态的增加和减少元素,实现了Collection和List接口,可以灵活的设置数组的大小。要注意的是ArrayList并不是线程安全的,因此一般建议在单线程中使用ArrayList。ArrayList的元素可以为null;

源码解析:

ArrayList底层使用数组存储元素,默认数组大小为10

//默认数组大小
private static final int DEFAULT_CAPACITY = 10;
//定义存储数组
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

1. indexOf(Object o)方法

//查找某个元素,返回找到的第一个的下标
public int indexOf(Object o)
{
    //如果查找null,返回元素为null的下标
    if (o == null)
    {
        for (int i = 0; i < size; i++)
            if (elementData[i] == null)
                return i;
    }
    else
    {
        //遍历数组,返回找到的第一个元素的下标
        for (int i = 0; i < size; i++)
            if (o.equals(elementData[i]))
                return i;
    }
    //查询不到返回-1
    return -1;
}

2. lastIndexOf(Object o)方法

//查找元素,返回找到的最后一个元素的下标,方法同indexOf相似
public int lastIndexOf(Object o)
{
    if (o == null)
    {
        for (int i = size - 1; i >= 0; i--)
            if (elementData[i] == null)
                return i;
    }
    else
    {
        //倒叙遍历数组,indexOf为正序
        for (int i = size - 1; i >= 0; i--)
            if (o.equals(elementData[i]))
                return i;
    }
    return -1;
}

3. get(int index)方法

//根据下标获取数组元素
public E get(int index)
{
    //检查索引是否越界
    rangeCheck(index);
    //返回下标所在的元素
    return elementData(index);
}
private void rangeCheck(int index)
{
    //如果索引大于数组长度,抛出索引越界异常
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

4. add(E e)方法:当数组容量不够时,扩容为原来的1.5倍

//添加元素
public boolean add(E e)
{
    //在加入元素前,检查数组容量是否足够
    ensureCapacityInternal(size + 1);
    elementData[size++] = e;
    return true;
}
private void ensureCapacityInternal(int minCapacity)
{
    //判断现在的ArrayList是不是空的,如果是空的,minCapacity就取默认的容量和传入的参数minCapacity中的大值
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
    {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    //判断是否需要扩容
    ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity)
{
    modCount++;
    // 添加一个元素后的长度大于数组长度时,进行扩容(只有在数组为空的时候,minCapacity为默认容量和传入参数的最大值,其余时候为当前数组元素个数+1)
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}
private void grow(int minCapacity)
{
    //原数组长度
    int oldCapacity = elementData.length;
    //扩容后的容量为原容量+原容量/2
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // 数组复制
    elementData = Arrays.copyOf(elementData, newCapacity);
}

5. set(int index, E element)方法 :替换掉原位置的元素

public E set(int index, E element)
{
    //检查index是否超出数组索引范围
    rangeCheck(index);
    E oldValue = elementData(index);
    // 替换掉原位置的元素
    elementData[index] = element;
    return oldValue;
}
private void rangeCheck(int index)
{
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

6. add(int index, E element)方法 :插入元素,后边的元素后移

public void add(int index, E element)
{
    //检查索引是否越界,同上
    rangeCheckForAdd(index);
    //检查数组容量是否足够
    ensureCapacityInternal(size + 1);
    //进行数组插入位置后的元素复制,后移一位
    System.arraycopy(elementData, index, elementData, index + 1
        , size - index);
    //插入元素
    elementData[index] = element;
    size++;
}

7. remove(int index)方法

public E remove(int index)
{
    //检查索引是否越界
    rangeCheck(index);
    modCount++;
    E oldValue = elementData(index);
    //删除元素后,需要移动的元素个数,即多少元素需要前移一位
    int numMoved = size - index - 1;
    if (numMoved > 0)
        //数组复制后迁移一位,待删除元素被覆盖
        System.arraycopy(elementData, index + 1, elementData, index
            , numMoved);
    //最后空出来的位置赋值null
    elementData[--size] = null;
    return oldValue;
}

这就是ArrayList底层实现原理,ArrayList就是动态数组,它提供了动态的增加和减少元素,以灵活的设置数组的大小。最后大家如果想要了解更多java入门知识,敬请关注奇Q工具网。

推荐阅读:

java方法怎么接收泛型实体?java方法如何调用?

jcreator如何使用?jcreator怎么配置?

java基础教程哪个好?如何规划学习java?