List:
List是collection的子接口,List下面又有ArrayList和LinkedList两个实现类,两个实现类中的方法大致相同,都有add、addAll、contains、get、indexOf、remove、set、size等方法,说说它们各自的特点ArrayList:
特点:1.可重复 2.有序底层是由一维数组实现的,与数组不同的是,ArrayList中每个元素可以是各种不同类型,但是编程中一般会对其加上泛型约束。
LinkedList:
特点:1.可重复 2.有序底层由双向链表实现,LinkedList中的每个组成部分叫做结点,每个结点具有三个属性:1.前一个结点的地址 2.该结点元素 3.后一个结点的地址 。每个LinkedList都具有两个全局变量:1.first(保存第一个元素结点的地址) 2.last(保存最后一个元素结点的地址)。
所以:LinkedList具有对第一个结点和最后一个结点直接操作的一些方法。
ArrayList vs LinkedList:
从增删改查四个方面来讨论两种List实现类的性能:增:
通过add源码来看:ArrayList的底层完全和一维数组相同,其初始时长度为10,变量size表示了当前添加元素存放的下标,存满时会调用扩容程序,即新建一个二倍于当前长度的数组,copy数据,再将其赋值给原数组,达到扩容目的。
所以 添加到末尾:进行添加操作时,普通情况下,ArrayList直接利用变量size作为元素下标进行添加,效率高。但是,如果遇到正好该扩容的情况时,添加这个元素,需要新建数组,copy所有元素,效率就不如LinkedList。 LinkedList进行添加操作时,调用linkLast(e)方法,实现为新建一个node结点,建立该结点和当前last指向的结点之间的关系(链接),修改last(保存队尾结点地址)内容,永远如此,不存在扩容的情况,当然,其效率比ArrayList普通情况下的添加更麻烦,效率更低。
插入(添加到队中):ArrayList利用下标插入,先判断是否越界,再将原插入位置元素到末尾全部往后移动一位,给插入下标赋值。每次插入都有大量元素的移动,效率较低。 而LinkedList
是通过下标作为循环条件找到你想插入的那个节点,有意思的是,它会根据插入的下标在该链表的前半段或是后半段来选择是从头向后遍历还是从尾部向前遍历,找到该结点后,再重新将你要插入的结点与其进行链接设置即可。由此看来,ArrayList需要元素的移动,LinkedList需要遍历,和链接设置,除遇到扩容时,ArrayList优于LinkedList,但是如果元素很多而插入的位置靠近队头时,ArrayList会有大量大量的元素移动,而LinkedList只需要从头少量的遍历,就可以取得该结点,连接即可。
删:
从remove源码来看:ArrayList: 根据元素内容进行删除时,先通过遍历找到该元素,将其后每个元素前移一位。根据下标进行删除时,先判断是否越界,不用遍历,找到该元素后将其后每个元素前移一位。
LinkedList: 根据元素内容进行删除时,通过遍历返回符合条件的结点,对其前后结点进行关系(链接)改变。根据下标进行删除时,也先判断是否越界,然后遍历链表,找到结点,对其前后结点进行关系(链接)改变。
ArrayList删除后需要大量元素移动。
所以,通过元素内容进行删除时,如果表很长,而且要删除的内容在前部,和增中一样,ArrayList需要大量元素移动,此时LinkedList效率更高,但如果不是删除的前半部分内容,由于都需要遍历,而ArrayList还需要元素移动,所以我估计还是LinkedList跟好
故:通过元素内容进行删除时,LinkedList效率更高。
而通过下标进行删除时和增的情形相同,ArrayList需要有元素移动,而LinkedList需要遍历查找,当被删除元素靠前时LinkedList效率更高。否则ArrayList效率更高。
改:
从set源码来看:ArrayList:直接通过下标找到该元素,直接赋值即可,非常方便。
LinkedList:遍历,找到当前结点,修改当前结点的元素值。
不用多说,在数据的修改方面,ArrayList完胜LinkedList。
查:
从contains和indexOf源码来看:两者的查询,都是利用遍历方式,找到指定元素,返回。而数组的遍历比链表的遍历更快,所以,在查询方面,ArrayList胜过LinkedList