一步一步解析java集合框架LinkedList源码(3)
2016-07-30 10:26
543 查看
我在阅读源码的过程中很多时候是没有头绪的。所以为了避免大家也遇到这种状况,源码不求全求大,做到“透过实践看源码”,分块分层。
介绍一些额外的添加操作
指定索引进行插入
运行结果:
zero
second
运行结果:
first
second2
源码分析:
介绍一些额外的添加操作
指定索引进行插入
public static void main(String[] args) { LinkedList<String> list=new LinkedList<String>(); list.add("first"); list.add("second"); list.add(0,"zero"); System.out.println(list.getFirst()); System.out.println(list.getLast()); }
运行结果:
zero
second
public static void main(String[] args) { LinkedList<String> list=new LinkedList<String>(); list.add("first"); list.add("second"); LinkedList<String> list2=new LinkedList<String>(); list.add("first2"); list.add("second2"); list.addAll(list2); System.out.println(list.getFirst()); System.out.println(list.getLast()); }
运行结果:
first
second2
源码分析:
/** * 将集合c中的元素全部添加进链表 */ public boolean addAll(Collection<? extends E> c) { return addAll(size, c); } /** *将集合c中的元素全部添加进链表 *addAll(Collection<? extends E> c)函数调用传递参数index==size *带参构造函数index==size==0 */ public boolean addAll(int index, Collection<? extends E> c) { checkPositionIndex(index); //将集合c转化成数组 Object[] a = c.toArray(); int numNew = a.length; if (numNew == 0) return false; Node<E> pred, succ; //index==size; if (index == size) { succ = null; pred = last; } else { succ = node(index); pred = succ.prev; } //遍历数组,每次添加至尾节点 for (Object o : a) { @SuppressWarnings("unchecked") E e = (E) o; //构造新节点,prev(前一节点)节点均是尾节点,第一次直接是last节点,以后每次是更新的尾节点 Node<E> newNode = new Node<>(pred, e, null); //pred==null,表明原链表没有数据 if (pred == null) first = newNode; else pred.next = newNode; pred = newNode;//将新构建的节点作为下个新节点的prev节点 } //succ==null if (succ == null) { last = pred; } else { pred.next = succ; succ.prev = pred; } size += numNew; modCount++; return true; }
/** * 通过索引添加元素 */ public void add(int index, E element) { checkPositionIndex(index); if (index == size) linkLast(element); else linkBefore(element, node(index)); } //检查索引的合理性 private void checkPositionIndex(int index) { //索引超出范围,抛出异常 if (!isPositionIndex(index)) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } /** * 索引值必须在合法范围内 */ private boolean isPositionIndex(int index) { return index >= 0 && index <= size; } /** * 返回对应索引index节点 */ Node<E> node(int index) { // assert isElementIndex(index); //size >> 1 表示size/2,通过这种比较可以更快的查找到节点 if (index < (size >> 1)) { Node<E> x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else { Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } } /** * 插入节点 * 在节点Node<E> succ前面插入 */ void linkBefore(E e, Node<E> succ) { // assert succ != null; final Node<E> pred = succ.prev; //首先构造新节点 final Node<E> newNode = new Node<>(pred, e, succ); //重新进行双向链接 succ.prev = newNode; //在首节点处插入,pred==null if (pred == null) first = newNode; else pred.next = newNode; size++; modCount++; } /** * 将元素e添加至链表末尾, * 双向的,类似于:first--->A---->B---->...--->last * <-- <--- <--- ...<-- */ void linkLast(E e) { //第一次添加数据,因为last并没有实例化,所以l不是指向last的引用,l=null final Node<E> l = last; //根据添加的元素创建一个节点,将last节点作为prev节点,next节点设置为空,随后设置 final Node<E> newNode = new Node<>(l, e, null); //将新构建的节点作为last节点,保证每次添加都添加至末尾 last = newNode; //第一次添加,将first指向newNode节点(新构建的) if (l == null) first = newNode; else l.next = newNode;//以后每次都将最后一个节点的next只想新节点 size++;//元素数递增 modCount++; }
相关文章推荐
- 第十六章 Lambda与Java8
- Java枚举类型(一)
- Spring控制反转与依赖注入
- spring线程池ThreadPoolTaskExecutor与阻塞队列BlockingQueue
- 在dos下运行java jar包,并把命令村为bat文件
- SpringMVC+MyBatis - 7 Spring自动扫描注解类的冲突问题
- IO流切割文件
- Java8 lambda表达式10个示例
- java 堆 栈 方法区的简单分析
- spring中的<context:component-scan base-package="" />的作用
- Eclipse 2015优化技巧
- Eclipse 2015优化技巧
- Eclipse 2015优化技巧
- Eclipse 2015优化技巧
- Eclipse 2015优化技巧
- Eclipse 2015优化技巧
- Eclipse 2015优化技巧
- Eclipse 2015优化技巧
- Eclipse 2015优化技巧
- Eclipse 2015优化技巧