Java 杂谈程序员

从数组、链表开始聊聊ArrayList、LinkedList、V

2018-06-21  本文已影响0人  whoami2019

本文提到的实现均是基于jdk 1.8,其他版本可能不同。 如果文章有错的地方欢迎指正,大家互相交流 , 欢迎评论大家一起讨论技术。

一、数组和链表介绍

数组和链表是两种基本的数据结构,虽然均是作为线性的数据结构,但是在内存存储上的表现不一样,所以也有各自的特点。

1.1、数组的特点

数组中5个学生连坐一起

1.2、链表的特点

链表中散列分布的5个学生

1.3、数组和链表总结

数组的优点

数组的缺点

链表的优点

链表的缺点

建议

对性能不敏感时,随便用哪个都可以,但是对性能有要求时,随机访问多新增删除少时建议用数组,相反,建议用链表

二、Collection集合体系的继承树

Collection集合体系的继承树

三、ArrayList源码赏析

3.1、插入元素,赏析扩容

插入元素,赏析扩容

ArrayList的底层实现是数组,而数组长度是固定的,ArrayList长度却是可变长的,其实ArrayList底层用的是扩容的手段,简单来说就是当容量不够时,将元素拷贝到一个长度更长的新数组。

所以ArrayList在插入元素时,先做的是数组扩容,因为新增一个元素,所以minCapacity = size+1,如果是第一次插入,则minCapacity默认为10,意思是ArrayList不可能一个一个的扩容,因为容量扩展的开销太大呀,若minCapacity > 当前的容量时才会进行扩容,否则不需要扩容直接插入元素即可。到这里,我们可以得知minCapacity 可以理解成客户端本次插入元素需要的最小容量的意思。minCapacity 其实也不是最终要扩容的数量,因为这只是客户端要求存放元素的最少容量,可是ArrayList也有自己的原则,它默认扩容0.5倍,若minCapacity 较大将按minCapacity 来扩容,否则就是扩容0.5倍。

3.2、移除元素,赏析对象回收细节

移除元素,赏析对象回收细节

第505行:elementData[--size] = null; // clear to let GC do its work,主动断开了栈与堆的连接,之后该对象就失去了引用,GC才能进行回收,不然没用的对象一直占用内存可能会导致内存溢出与内存泄露。

3.3、总结及建议

ArrayList的底层实现原理相对不难,难点主要是扩容。虽然每次扩容默认增大0.5倍,但是扩容涉及到元素复制到新数组,开销是比较大的。所以建议:

当预计到插入元素较多时,在实例化时利用public ArrayList(int initialCapacity)构造函数指定初始容量,若是在插入元素的过程中才知道接下来插入元素操作频繁,可以用public void ensureCapacity(int minCapacity)方法扩容。

四、Vector与ArrayList的区别

Vector是jdk1.2的类了,比较老旧的一个集合类。

注释上写着是jdk 1.2的类

Vector底层也是数组,实现原理跟ArrayList几乎一样,与ArrayList最大的区别就是:同步(线程安全)

还有个区别ArrayList在底层数组不够用时在原来的基础上扩展0.5倍,Vector是扩展1倍。

Vector是同步的,我们可以从方法上就可以看得出来~

方法上都有synchronized

五、LinkedList实现原理

LinkedList节点内部类

该LinkedList内部类,就是ArrayList的节点类。根据属性,可以猜到LinkedList的底层实现应该是个双向链表,没错,就是双向链表。

知道了节点对象后,只要懂得链表的知识,加上逻辑思维能力,自己实现一个简单的LinkedList应该不是难事,所以LinkedList就不多说了。

最后,要补充一下的就是:从上面的Collection继承树中可以看到,LinkedList除了实现List接口外,还实现了Deque接口,Deque接口是个双向队列。因此,LinkedList除了能够存放元素外,还可以实现队列和栈的功能,可谓是一个功能强大的类。

六、总结

其实集合的源码看起来并不是很困难,遇到问题可以翻一翻,应该是能够看懂的。

ArrayList、LinkedList、Vector算是在面试题中比较常见的的知识点了。下面我就来做一个简单的总结:

ArrayList

LinkedList

底层实现是双向链表[双向链表方便实现往前遍历]

Vector

底层是数组,现在已少用,被ArrayList替代,原因有两个:

  Vector所有方法都是同步,有性能损失。

  Vector初始length是10 超过length时 以100%比率增长,相比于ArrayList更多消耗内存**。**

总的来说:查询多用ArrayList,增删多用LinkedList。

上一篇下一篇

猜你喜欢

热点阅读