List代表一种线性表的数据结构,ArrayList则是一种顺序存储的线性表,ArrayList底层则采用数组来保存每个集合元素,LinkedList则是一种链式存储的线性表,它实现了List的接口,还是实现了Deque的接口,LinkedList不仅可以当队列,和双向链表使用,也可以当做栈来使用;
1.ArrayList查询速度相对于LinkedList会比较快,但是插入和删除会比LinkedList慢,为什么?
因为ArryaList使用的链表,底层用的数组做存储;
ArrayList 要保证底层封装数组的长度要小于ArrayList里面元素的个数;
当进行删除操作的时候,整体的元素要想前移动一位,被删除的位置被置为空;
当进行添加的操作的时候,整体的元素向后移一位;
//删除源代码
public E remove(int index){
RangeCheck(index) //大于或者等于size的时候就会抛出异常
modCount++;
E oldValue=(E) elementData[index];
int numMoved=size-index-1; //算出需要整体移动的元素个数;
if(numMoved>0)
System.arraycopy(elementData,index+1,elementData,index,numMoved); //copy
elementData[--size]=null; //释放被删除的元素,以便GC回收该元素
return oldValue;
}
//get方法的时候
public E get(int index){
rangeCheck(index); //如果index超过了集合的长度,则会抛出异常
//取出index索引处的元素
return (E)elementData[index]
}
get方法的时候会更快一点,因为它底层是一个数组,根据索引去取就很快了
LinkedList本质上就是一个双向链表,使用内部类来进行保存每个集合的元素。
Entry对象则代表链表上面一个节点,next变量指向下一个节点,previous则指向上一个节点。
//在指定为插入新节点
public void add(int index,E element ){
addBefore(element,(index==size?header:entry(index))); //如果不等于的size就会在指定索引处之前插入新节点;
}
如果当前插入的位置刚好等于这个这个链表size 就会在头部插入,否则就会entry(index),搜索指定索引处的元素;
查找的话,ArrayList底层数组,查找根据索引就会更快速找到值,但是LinkedList就会比较麻烦了,它会逐个元素进行查找;
//查找:
private Entry<E> entry(int index){
if(index<0||index>=size)
throw new Exception
Entry<E> e=header;
if(index<(size>>1)) //如果index 小于size/2 则从头部进行查询
{
for(int i=0;i<=index;i++)
e=e.next;
}else{ //否则会从尾部进行查询
for(int i=size;i>index;i--)
e=e.previous;
}
return e
}
//如果单纯进行插入就简单了:
private Entry<E> addBefore(E e,Entry <E>)
{
Entry<E> newEntry=new Entry<E>(e,entry,entry.previous)
newEntry.previous.next=newEntry;
newEntry.next.provious=newEntry;
size++;
modCount++;
return newEntry;
}
所以说LinkedList在指定位置进行插入的时候,排除index==size 因为这种情况会在头部进行插入,而其他会进行搜索,根据index,找到entry对象,这个搜索就会消耗很大性能了;