同:
都是List接口实现类,存储有序的,可重复的数据。
不同:
1ArrayList作为List接口主要实现类,效率高,但线程不安全,可以使用Collections 类中提供的synchronizedXxx() 方法, 该方法可使将指定集合包装成线程同步的集合,从而可以解决
多线程并发访问集合时的线程安全问题,底层使用object[] elementData储存。
2.LinkedList底层使用双向链表储存,所以对于频繁的插入,删除操作使用此类比ArrayList高;
3.ArrayList底层源码解析:
jdk7情况下:
一上来就直接底层创建长度为10的Object[]数组elementData,当底层添加数组容量不够时则扩容,默认情况下扩容为原来的1.5倍,同时将原来数组的数据复制到新数组中
ArrayList list=new ArrayList();//底层创建了长度是10的Object[]数组elementData
list.add(123);//elementData[0]=new Integer(123);
.
.
.
list.add(11)//如果此次添加导致底层数组不够则扩容
jdk 8中ArrayList的变化:
ArrayList list =new ArrayList();//底层Object[] elementData初始化为{},没有创建长度为10的数组
list.add(123);//当第一次调用add()时才创建长度为10的数组并把123添加进去
后续的添加和扩容操作与jdk 7 无异。
建议:开发中使用带参构造器指明集合容量:
ArrayList list=new ArrayList(int capacity);
小结:jdk7中的ArrayList的对象的创建类似于单例的饿汉式,而jdk8中的ArrayList的对象
的创建类似于单例的懒汉式,延迟了数组的创建,节省内存。
LinkedList的源码分析:
LinkedList list=new Linkedlist();
//内部声明了Node类型的的first(起始节点)和last(尾节点)属性,默认值为null
list.add(123)
//创建Node对象,把123封装到Node里
其中,Node定义为:体现了LinkedList的双向链表的说法
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
内存:
LinkedList比ArrayList更占内存,因为LinkedList每一个节点会有两个引用,分别指向前一个结点和后一个结点;
各自的优缺点:
ArrayList是基于索引(index)的数据结构,所以它使用索引在数组中读取和搜索数据是很快的。ArrayList获取数据的时间复杂度是O(1),但要删除,插入数据的开销很大,因为这涉及到重排数组中的所有数据。
LinkedList的插入和删除就很快,因为LinkedList底层直接使用双向链表,插入和删除数据时直接在相应位置的相关节点改变索引指向即可,不需要重排数据。
什么情况下使用LinkedList,而不用ArrayList:
1.你的应用不会随机访问数据时。因为你如果想要随机访问数据又使用的LinkedList的话,访问第N个数据则你就需要从第一个元素开始遍历到第N个元素,然后读取数据。
2.你的应用要更多的插入和删除元素,更少的读取数据时。