您的位置:首页 > 编程语言 > Java开发

java LinkedList 源码解读

2016-11-09 10:03 246 查看
一直很少用LinkedList,一般都用ArrayList.有时碰到面试问起二者区别。于是仔细研究了一下。发现二者实现方式上相差很大。

ArrayList内部是通过一动态数据存储的。所以查找数据很快。根据INDEX,查数据效率高。数据存储在数组中。

LinkedList内数据根本没有固定的容器存储。而是通过对象关联引用,一层一层深入下去的。简单的说,就是保存在一个对象的无限引用中,引用链有多深取决数据量的大小。

LinkedList类声明如下:
可以发现 LinkedList继承了 AbstractSequentialList抽象类,而不是像 ArrayList和 Vector那样实现 AbstractList,实际上,java类库中只有 LinkedList继承了这个抽象类,正如其名,它提供了对序列的连续访问的抽象:

LinkedList的底层是 Deque双向链表,实现了 Deque接口,而 Deque接口继承于 Queue接口,因此,在java中,如果要实现队列,一般都使用 LinkedList来实现。


Node结点

Node节点 一共有三个属性:item代表节点值,prev代表节点的前一个节点,next代表节点的后一个节点。

LinkedList中关于链表结点的定义如下:
每个结点都有一个前驱和后继结点,并且在 LinkedList中也定义了两个变量分别指向链表中的第一个和最后一个结点:


添加(add)操作


LinkedList总结

LInkedList添加操作时每个新添加的对象都会被放到新建的Node对象中,Node对象中包含加入的对象和前后指针属性(pred和next,pred和next其实都是Node对象,直接存放的就是当前对象的前一个节点对象和后一个节点对象,最后一个及节点的next值为null),然后将原来最后一个last节点的next指针指向新加入的对象,即可


addAll操作

总结

LinkedList在某个位置插入元素是通过将原位置节点的前一个节点的后一个指针指向新插入的元素,然后将原位置的节点的前一个指针指向新元素来实现的,相当于插入元素后后面的元素后移了,但是不是像ArrayList那样将所有插入位置后面的元素都后移,此处只是改变其前后节点的指向


删除操作

总结:

LinkedList删除操作是通过将index位置上的前一个节点的next执行index位置的后一个节点,同时将后一个节点的pred指向前一个节点,然后将index位置上的Node节点对象属性都置空来实现的,置空后的Node对象会被GC垃圾回收期回收掉。


修改操作

总结:

LinkedList中的实际数据保存在节点对象的item属性中


查询操作

总结:

插叙操作是通过node方法实现的,而node方法是通过先判断index位置是在整个链表的前一半还是后一半来遍历前一半或者后一半元素来获取index位置上的元素


LinkedList和ArrayList的大致区别

1、ArrayList继承于 AbstractList, LinkedList继承于 AbstractSequentialList;

2、ArrayList基于数组, LinkedList基于双向链表,对于随机访问, ArrayList比较占优势,LinkedList插入、删除元素比较快,如果只要调整指针的指向那么时间复杂度是O(1),但是如果针对特定位置需要遍历时,时间复杂度是O(n),也就是LinkedList在随机访问元素的话比较慢;

3、LinkedList没有实现自己的 Iterator,但是有 ListIterator和 DescendingIterator;

4、LinkedList需要更多的内存,因为 ArrayList的每个索引的位置是实际的数据,而 LinkedList中的每个节点中存储的是实际的数据和前后节点的位置;

5、ArrayList 和 LinkedList都是非同步的集合。

6、和ArrayList一样,LinkedList也是非线程安全的,只有在单线程下才可以使用。为了防止非同步访问,可以采用如下方式创建LinkedList:List list= Collections.synchronizedList(new LinkedList());

7、LinkedList基于双向链表实现,元素都可以为null。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: