关于ArrlistList和LinkedList的区别

1.共同点

2.不同点

2.1底层原理

2.2优缺点

Arraylist和Linkedlist的共同点:

他们都是单例集合接口Collection的子接口list的实现类,因此它们具有list接口的特点:元素存储和取出是有序的,且集合中的元素可以重复。另外,除了Linkedlist几个独有的方法之外,他们具有绝大部分相同的方法。

Arraylist和Linkedlist的不同点:

1.底层原理:

Arraylist:
Arraylist的底层存储形式:

对于Arraylist集合,它有几个成员变量:

       由以上几个成员变量可以看出,对于Arraylist集合来说,他的底层存储方式为Object类型的数组elementDate。而一个数组在定义时就必须要初始化它的长度,而这个数组是怎样初始化长度的呢?

Arraylist初始化的方式(构造方法):

      对于Arraylist集合底层的数组elementDate来说,共有三种初始化的方式,即Arraylist类中有三个构造方法,我们来具体看一下:

此为Arraylist类的无参构造,通过此构造方法,我们不难看出,此时数组elementDate的初始化长度为0。

此为Arraylist类参数为int initialCapacity的构造方法,通过此构造方法,我们可以看出它将我们传入的参数作为了数组elementDate的初始化长度,即做到了自定义集合的长度。

      此为Arraylist类中参数为collection类单例集合c的构造方法,通过此构造方法,我们可以看出,通过我们传入的集合c的长度,完成了对数组elementDate长度的初始化。

Arraylist的扩容机制:

      对于第一种初始化的方式,我们知道了数组elementDate初始化的长度为0,那一个长度为0的数组要怎样添加存储元素呢,这就不得不说到它的扩容机制了:

    通过上面代码我们可以看出,当集合中首次添加元素时,数组初始化长度由开始的0变成了现在的DEFAULT_CAPACITY=10.。那当我们添加到第十一个元素时,又是如何扩容的呢?

     通过以上代码可以看出,扩容时是按照之前初始化长度的1.5倍进行扩容。如果一次添加多个元素,超过了扩容后的长度,此时也有相应的补偿机制,即将所需要的最小长度直接复制给数组elementDate初始化的长度。

     还有一种情况,就是添加元素到集合中间某个位置时,又是怎样实现的呢?

     观察上述代码发现,当我们将元素添加到集合下标为index的位置时,在集合中从原index位置的元素开始整体都往后移动了一位,再将我们要添加的元素赋值到index的位置。如果需要多次频繁的往集合中间添加元素,此类集合还会方便吗?

Linkedlist:
Linkedlist的底层存储形式:

对于Linkedlist类,它的成员变量如下:

      与Arraylist集合不同的是,Linkedlist底层存储形式不是数组,而是一个又一个的Node型节点,它们双向链接,形成了一个“双向链表”。

Linkedlist的初始化方式:

       对于Arraylist集合,初始化的是底层数组elementDate的长度,那对于Linkedlist集合初始化的是什么呢?对于上面的成员变量我们发现了两个变量; Node first和Node last,其实它们表示的即是linkedlist集合底层双向链表的起始节点和结束节点。

       在linkedlist类中有两个构造方法,我们一起来看看它们是如何初始化Node节点的呢。

        此为linkedlist类中的无参构造,我们可以看出并未对成员变量进行初始化操作,即此时成员变量first和last均为null。因为集合中没有元素,即底层链表中的first节点和last节点都没有指向。

      当我们使用add方法为集合中添加中元素时,它是如何实现的呢?

         我们知道,使用add方法是默认添加到集合末尾,即等同于addlast方法。观察上面代码,此时last仍为null,则在新节点newNode中,成员变量item为我们传入的参数,prev和next均为null,因为现在只有这一个节点,所以此节点的前一个和后一个都没有指向。而在整个链表中,成员变量first和last均指向了新的节点newnode,因为此时链表中只有这一个节点,所以它既是起始节点,也是结束节点。

       当我们开始添加第二个元素时,此时在新节点newnode中的成员变量prev开始有了指向,即指向了上一个节点,而在上一个节点中的成员变量next也有了指向,即指向了新节点newnode。此时即形成了一个双向链表,在这个链表中,first指向了前面的节点,而last指向了新的节点。

      还有一种情况,就是在链表的中间添加一个元素节点,此时又是如何实现的呢?

        观察上面代码我们发现,当我们要在双向链表中下标值为index位置添加一个新的节点时,它先会先找到链表中原本在index位置的节点,并将其定义为节点succ,并定义一个节点pred为节点succ的上一个节点。在最下面的代码中,原本节点pred的变量next原本指向节点succ,succ的变量prev指向pred,经过此代码后,新加的节点newnode的变量prev指向了节点pred,next指向了节点succ。再将节点succ的上一个节点由pred重新赋值成新加节点newnode,此时节点succ的变量prev由开始指向pred变成指向新加节点newnode。再经过判断将节点pred的下一个节点由succ变成了新加节点newnode,此时节点pred的变量next由原来指向succ改为指向新加节点newnode。此时便完成了在边表中间指定位置添加新元素节点的操作,在此操作中我们可以看出,再新加元素时,只需要改变新加元素节点和原本此位置节点和前一个节点之间的指向即可,并不需要像Arraylist集合一样将添加位置后面的所有元素整体向后移动。因此就此方面看,linkedlist要更加方便。

linkedlist中还有一种有参构造,代码如下:

         此为linkedlist类参数为collection集合的构造方法,此构造方法是通过collection集合对linkedlist类中的成员变量node first和node last进行初始化,具体实现与上面添加元素类似,这里不再赘述。  

Linkedlist的扩容机制:

        由于linkedlist的底层存储形式为双向链表,当添加元素时,会自动创建新的节点。因此对于linkedlist集合来说,并不涉及扩容问题。

linkedlist和Arraylist的优缺点:

Arraylist集合:

优点:便于频繁查看集中的某个元素,因为底层存储形式为数组,可以直接通过数组下标直接获取到需要查看的元素信息。

缺点:1.可能造成内存空间浪费:因为涉及扩容问题,当一开始不清楚需要存储的元素个数时,扩               容后可能会空出很多,造成内存空间浪费。

            2.不方便集合中间频繁添加或删除元素。通过底层原理可以看出,如                   果要在集合中间指定位置添加或删除元素,则在此位置之后的所有元素都要相应的移                       动。

Linkedlist集合:

优点:1.便于在集合中间频繁添加或删除元素。通过底层原理我们知道,添加或删除元素时,只需               改变对应的几个节点的指向即可,而不需要其余的元素一起跟着移动。

            2.不会造成内存浪费:因为不涉及扩容问题,添加多少个元素就会创建多少个节点。

缺点:1.不便于查看集合中的元素:因为底层存储形式的缘故,它查找元素时不能像Arraylist一些              通过数组下标直接查看,而是通过节点下表与集合1/2长度的关系,从起始开始或者从末尾               开始一个一个查找。

            2.节点本身会占用更大内存:在linkedlist集合的链表中,每一个节点除了存储基本的元素                信息之外,还有额外的两个变量prev和next,用于指向前一个节点和后一个节点,因此会                 占用更大的内存。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值