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

本文提到的实现均是基于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

  • 底层实现是数组

  • ArrayList的默认初始化容量是10,每次扩容时候增加原先容量的一半,也就是变为原来的1.5倍

  • 在增删时候,需要数组的拷贝复制(navite 方法由C/C++实现)

LinkedList

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

Vector

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

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

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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容

  • 一.线性表 定义:零个或者多个元素的有限序列。也就是说它得满足以下几个条件:  ①该序列的数据元素是有限的。  ②...
    Geeks_Liu阅读 2,697评论 1 12
  • 在一个方法内部定义的变量都存储在栈中,当这个函数运行结束后,其对应的栈就会被回收,此时,在其方法体中定义的变量将不...
    Y了个J阅读 4,416评论 1 14
  • 回到家的孟信,自信心倍增,白天刻苦修炼,夜间在被窝里偷偷研究机关术,沉迷其中,乐不思蜀,而假期也就这样不知不觉的过...
    梦游生阅读 203评论 0 0
  • 肯定是成功的润滑剂和助推力;抱怨是成功的拦路虎和绊脚石。既然我们都懂得抱怨于己无益,所以一定要时刻提醒自己:只要对...
    张锐城分析阅读 244评论 0 0
  • 辣条和烧烤,是再普通不过的东西了,路边,街上,巷子的小卖部里,都有着它们的身影。它们身旁,往往围了一大群的孩子,也...
    phantomses阅读 583评论 0 1