Java集合底层原理(1)

Java集合底层原理

现在面试的时候相当多的面试官喜欢询问Java中集合的底层原理,因此整理后在这里对Java中集合的底层原理进行一下简单的介绍。
首先我们来看一下Java中集合的种类。
在这里插入图片描述
Java中集合主要有两个分类,单列集合和双列集合他们分别通过实现Collection和Map接口来实现,而Collection下又是由两个接口List和Set所继承。接下来我们就分别对其中的一些在Java中的底层实现原理做一下解析。

ArrayList集合的底层原理

首先来看一下ArrayList集合所实现的接口有哪些
在这里插入图片描述
其中所实现的RandomAccess接口让ArrayList能够快速随机访问,Serializable和Cloneable让ArrayList接口拥有序列化传输和克隆的能力。
1.ArrayList底层是由一个数组来实现的。通过它的一些成员变量就可以看出来。

private static final int DEFAULT_CAPACITY = 10;//创建ArrayList集合时,数组的默认长度
private static final Object[] EMPTY_ELEMENTDATA = {};//当我们创建ArrayList集合时指定其长度为0时,ArrayList就会使用这个数组来完成初始化
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//当我们没有指定数组长度,类缺省选择的默认数组
transient Object[] elementData;//数组列表中存储元素的数组缓存区,数组列表的长度就是这个数组缓存区的长度,当带有elementData ==的数组添加第一个元素时,DEFAULTCAPACITY_EMPTY_ELEMENTDATA将会被扩展为DEFAULT_CAPACITY,因为带有transient关键字进行修饰,所以不会被序列化
private int size;//ArrayList集合的大小(其实是数组内含有的元素个数)

2.ArrayList的add()方法
它的源码如下

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

可以看出add()方法就是在数组元素的末尾添加新传入的值。但在之前首先调用了ensureCapacityInternal(size + 1),其实这个方法就是对要存储元素的数组大小进行判断,如果当前数组的大小小于(size+1),就对数组进行扩容,扩容后的数组大小时旧数组大小的1.5倍,然后利用Arrays.copyOf()方法,将旧数组的值复制到新数组中,这一段主要在ArrayList的grow()方法中实现。
3.ArraysList的set()方法

public E set(int index, E element) {
        rangeCheck(index);

        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }

主体就是先取出旧元素,再把旧元素在数组的位置上赋上新元素的值,最后再返回旧元素,但在这之前还调用了rangeCheck(index)方法,这个方法其实就是对输入的index的值进行判断,如果index的值大于数组内元素,就抛出一个数组下标越界异常
4.ArrayList的remove()方法

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);
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }

首先还是先对传入的index是否越界进行检查,根据index获取要存储的值并保存下来,然后再根据index判断移除的元素是否是最后一个元素,是的话只需要把这个元素的值赋值为null就可以了,否则就需要使用System.arraycopy(elementData, index+1, elementData, index,
numMoved)方法来使数组index+1后的元素都向前移动一位,最后返回刚才保存的被删除的元素就OK了
5.ArrayList的get()方法

public E get(int index) {
        rangeCheck(index);

        return elementData(index);
    }

非常简单和上面的set()没有什么差别,就不解释了
6.ArrayList的indexOf()方法

public int indexOf(Object o) {
        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;
        }
        return -1;
    }

首先对传入的对象进行判断,如果是空值得话,就遍历数组(但仅仅遍历下标0到下标size-1的元素)返回数组中第一个为空值的index,否则就返回第一个与数组中元素相等的下标值。
7.ArrayList的优缺点
ArrayList的优点:
使用下标查询元素效率很高
凭借下标遍历元素效率高
自动扩容,每次扩容后的容量是原来的1.5倍,使用时不用考虑扩容问题
ArrayList的缺点:
插入和删除效率低
线程不安全
使用类似indexOf()的方式来查询集合内元素时效率低

今天就到此为止,关于Java其他的集合的底层实现原理会后续在我的主页更新,有兴趣的同学可以点个关注0.0,如果文章有什么不对的地方,欢迎指出

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值