Java记录 -49- LinkedList源码剖析
2015-10-29 00:41
441 查看
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, Serializable
List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现
List 接口外,LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。
此类实现 Deque 接口,为 add、poll 提供先进先出队列操作,以及其他堆栈和双端队列操作。
所有操作都是按照双重链接列表的需要执行的。在列表中编索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。
LinkedList就是一个链表,其底层使用了双向链表来实现。
LinkedList的两个构造函数实现:
Entry作为节点,构造函数创建了一个空的双向链表。而带参数的构造函数则先调用了不带参数的构造函数,然后将传过来的集合里的元素都添加到链表里。
Entry作为LinkedList的一个内部类实现。Entry实现了Node功能,element存放数据信息,next指向下一个节点,previous指向前一个节点。其构造函数中实现了数据赋值,和节点指向。
LinkedList的add方法调用了addBefore方法,并将header传入。在addBefore中先创建了一个Entry节点,然后修改指针指向。完全都是双向链表的操作。而在指定位置添加也是调用addBefore方法,只是没有直接传递header节点,而是传递了要添加位置的节点。
LinkedList适合挨个遍历元素,即使指定了位置查询,也需要挨个遍历,因为它只知道链表的头header位置,要通过header去寻找其他节点,比如下面的getFirst和getLast方法是最简单的,直接使用header就可以找到。但指定位置的get方法则需要调用entry定位节点的方法来实现,上面添加元素到指定位置时也需要调用entry方法来找到指定位置的节点。entry方法也是通过header来挨个遍历寻找节点。
List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现
List 接口外,LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。
此类实现 Deque 接口,为 add、poll 提供先进先出队列操作,以及其他堆栈和双端队列操作。
所有操作都是按照双重链接列表的需要执行的。在列表中编索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。
LinkedList就是一个链表,其底层使用了双向链表来实现。
LinkedList的两个构造函数实现:
Entry作为节点,构造函数创建了一个空的双向链表。而带参数的构造函数则先调用了不带参数的构造函数,然后将传过来的集合里的元素都添加到链表里。
private transient Entry<E> header = new Entry<E>(null, null, null); private transient int size = 0; /** * Constructs an empty list. */ public LinkedList() { header.next = header.previous = header; } /** * Constructs a list containing the elements of the specified * collection, in the order they are returned by the collection's * iterator. * * @param c the collection whose elements are to be placed into this list * @throws NullPointerException if the specified collection is null */ public LinkedList(Collection<? extends E> c) { this(); addAll(c); }Entry作为链表节点,其实现如下:
Entry作为LinkedList的一个内部类实现。Entry实现了Node功能,element存放数据信息,next指向下一个节点,previous指向前一个节点。其构造函数中实现了数据赋值,和节点指向。
private static class Entry<E> { E element; Entry<E> next; Entry<E> previous; Entry(E element, Entry<E> next, Entry<E> previous) { this.element = element; this.next = next; this.previous = previous; } }LinkedList的add方法:
LinkedList的add方法调用了addBefore方法,并将header传入。在addBefore中先创建了一个Entry节点,然后修改指针指向。完全都是双向链表的操作。而在指定位置添加也是调用addBefore方法,只是没有直接传递header节点,而是传递了要添加位置的节点。
/** * Appends the specified element to the end of this list. * * <p>This method is equivalent to {@link #addLast}. * * @param e element to be appended to this list * @return <tt>true</tt> (as specified by {@link Collection#add}) */ public boolean add(E e) { addBefore(e, header); return true; } /** * Inserts the specified element at the specified position in this list. * Shifts the element currently at that position (if any) and any * subsequent elements to the right (adds one to their indices). * * @param index index at which the specified element is to be inserted * @param element element to be inserted * @throws IndexOutOfBoundsException {@inheritDoc} */ public void add(int index, E element) { addBefore(element, (index==size ? header : entry(index))); } private Entry<E> addBefore(E e, Entry<E> entry) { Entry<E> newEntry = new Entry<E>(e, entry, entry.previous); newEntry.previous.next = newEntry; newEntry.next.previous = newEntry; size++; modCount++; return newEntry; }获取数据元素:
LinkedList适合挨个遍历元素,即使指定了位置查询,也需要挨个遍历,因为它只知道链表的头header位置,要通过header去寻找其他节点,比如下面的getFirst和getLast方法是最简单的,直接使用header就可以找到。但指定位置的get方法则需要调用entry定位节点的方法来实现,上面添加元素到指定位置时也需要调用entry方法来找到指定位置的节点。entry方法也是通过header来挨个遍历寻找节点。
public E get(int index) { return entry(index).element; } public E getLast() { if (size==0) throw new NoSuchElementException(); return header.previous.element; } public E getFirst() { if (size==0) throw new NoSuchElementException(); return header.next.element; } /** * Returns the indexed entry. */ private Entry<E> entry(int index) { if (index < 0 || index >= size) throw new IndexOutOfBoundsException("Index: "+index+ ", Size: "+size); Entry<E> e = header; if (index < (size >> 1)) { for (int i = 0; i <= index; i++) e = e.next; } else { for (int i = size; i > index; i--) e = e.previous; } return e; }
相关文章推荐
- spring远程服务知识梳理
- struts2和jsp的数据传值
- 关于Java中几种方法块的执行过程分析
- MyEclipse(Eclipse)安装后需要进行的配置
- JDK动态代理和Cglib的动态代理
- spring+jersey+c3p0构建restful webservice(数据源采用c3p0)
- Spring和SpringMVC的关系
- maven添加 xfire-all-1.2.6.jar 导致的spring配置文件异常
- Java中String类型的参数传递问题的解析
- android导入eclipse项目后,出现如下问题
- MyBatis整合Spring的实现(13)
- MyBatis整合Spring的实现(14)
- countDownLatch 与 CyclicBarrier 区别
- countDownLatch 与 CyclicBarrier 区别
- 设计模式之-工厂模式
- 两种方法安装TestNG Eclipse插件
- 对Spring的IoC和DI最生动的解释
- Spring核心技术总结一
- Java开发中的设计模式
- java 时间区间的处理