java8集合框架LinkedList类实现自己简单的理解
2016-09-07 23:48
906 查看
参考文献
LinkedList与ArrayList一样实现List接口,只是ArrayList是List接口的大小可变数组的实现,LinkedList是List接口链表的实现。基于链表实现的方式使得LinkedList在插入和删除时更优于ArrayList,而随机访问则比ArrayList逊色些。 LinkedList实现所有可选的列表操作,并允许所有节点数据部分为null。
除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾add, get、remove元素提供了统一的命名方法。这些操作允许将LinkedList链接列表用作堆栈、队列或双端队列。 此类实现 Deque 接口,为 add、poll 提供先进先出队列操作,以及其他堆栈和双端队列操作。
所有操作都是按照双重链接列表的需要执行的。在列表中编索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。
同时,与ArrayList一样此实现不是同步的。
定义
从代码中我们可以看出LinkedList继承AbstractSequentialList,实现List、Deque、Cloneable、Serializable。其中AbstractSequentialList提供了 List 接口的骨干实现,从而最大限度地减少了受“连续访问”数据存储(如链接列表)支持的此接口所需的工作,从而以减少实现List接口的复杂度。Deque一个线性 collection,是一个双端队列,支持在两端插入和移除元素,定义了双端队列的操作。
LinkedList中主要提供了三个基本属性
LinkedList提高了两个构造方法:LinkedLis()只是一个空方法和LinkedList(Collection
对于上面还有一个node(index)方法感觉处理的特别好。
给队列增加元素,除了上面介绍的deque接口的那些方法对对头队尾有特定方法外。
一般的方法
LinkedList还提供了其他的Deque接口增加方法:
其他的移除方法:
查询方法:
对于查找方法,无非就是迭代,比对,然后就是返回当前值。
使用LinkedList实现Stack效果
将LinkedList当中队列来使用
LinkedList与ArrayList一样实现List接口,只是ArrayList是List接口的大小可变数组的实现,LinkedList是List接口链表的实现。基于链表实现的方式使得LinkedList在插入和删除时更优于ArrayList,而随机访问则比ArrayList逊色些。 LinkedList实现所有可选的列表操作,并允许所有节点数据部分为null。
除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾add, get、remove元素提供了统一的命名方法。这些操作允许将LinkedList链接列表用作堆栈、队列或双端队列。 此类实现 Deque 接口,为 add、poll 提供先进先出队列操作,以及其他堆栈和双端队列操作。
所有操作都是按照双重链接列表的需要执行的。在列表中编索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。
同时,与ArrayList一样此实现不是同步的。
定义
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable {
从代码中我们可以看出LinkedList继承AbstractSequentialList,实现List、Deque、Cloneable、Serializable。其中AbstractSequentialList提供了 List 接口的骨干实现,从而最大限度地减少了受“连续访问”数据存储(如链接列表)支持的此接口所需的工作,从而以减少实现List接口的复杂度。Deque一个线性 collection,是一个双端队列,支持在两端插入和移除元素,定义了双端队列的操作。
deque主要接口方法。 add操作 void addFirst(E e);push(); //插入一个元素到队列头,如果队列空间受限用offerFirst方法更好 void addLast(E e);add(e); //插入一个元素到队列尾,如果队列空间受限用offerFirst方法更好,效率更高 boolean offerFirst(E e); boolean offerLast(E e); offer(e) 删除操作,获取并从队列删除元素 E removeFirst();remove();pop();//删除首元素 // 相比poll那组就是如果队列是空的这个方法进行删除操作会输出异常 E removeLast(); //删除末尾元素 //和上面两个方法一样 E pollFirst();poll() ; //队列如果是空,返回null E pollLast(); 查询操作,获取元素旦不删除元素 E getFirst();element();//获取首元素 E getLast();//获取最后一个元素 //上面两个方法相比peek方法那组,如果队列为空抛异常。 E peekFirst();peek(); E peekLast();
LinkedList中主要提供了三个基本属性
transient int size = 0;//元素个数 transient Node<E> first;//指向队列首元素 transient Node<E> last;//指向队列末尾元素 这个类是节点类,双向链表结构 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提高了两个构造方法:LinkedLis()只是一个空方法和LinkedList(Collection
public LinkedList(Collection<? extends E> c) { this(); addAll(c); } public boolean addAll(Collection<? extends E> c) { return addAll(size, c);//在队列末尾插入 } //这个方法一组数据插入队列LinkedList的方法,挺有代表性的。 public boolean addAll(int index, Collection<? extends E> c) { checkPositionIndex(index);//索引边界检查 Object[] a = c.toArray();//将collection的元素数据部分拿出来用于等下操作 int numNew = a.length; if (numNew == 0) return false;//如果c是空的话那么就返回false Node<E> pred, succ;//定义两个节点指针,指向插入点前后的节点元素 if (index == size) {//如果是在队列末尾插入的话 succ = null;//size位置指针succ为空 pred = last;//pred指向size位置前一个节点 } else { succ = node(index);//如果在队列中间插入,那么succ指向index这个节点 pred = succ.prev;//pred当然指向succ之前那个节点 } for (Object o : a) { @SuppressWarnings("unchecked") E e = (E) o;//类型强转,遍历数组每一个元素 Node<E> newNode = new Node<>(pred, e, null); //新建一个以e数据的节点 if(pred ==null) //如果刚插入时候是一个空队列那么对首节点指针赋值下 first = newNode; else pred.next = newNode; //将新建节点和插入节点之前一个节点建立联系 pred = newNode;//pred遍历到下一个节点准备插入下一个新建节点,这不一定不能少。 } //遍历插入完了后,进行写最后指针指向的问题扫尾 if (succ == null) { last = pred; } else { pred.next = succ;//如果是中间插入,需要使得pred的next属性指向succ指向的节点 succ.prev = pred;//succ指向节点的pred属性指向pred指向的节点 } size += numNew; modCount++; return true; }
对于上面还有一个node(index)方法感觉处理的特别好。
Node<E> node(int index) { // assert isElementIndex(index); //这里为了减少遍历次数,特意将index和size的一半对比。感觉处理手法比较新颖。(size >> 1)就是除2的操作。 if (index < (size >> 1)) { //index少于size的一般,那么找这个node只要在前半部分遍历就行 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; } }
给队列增加元素,除了上面介绍的deque接口的那些方法对对头队尾有特定方法外。
一般的方法
//第一个 public boolean add(E e) { linkLast(e);//将元素e增加到队列尾部 return true; } void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null);//新建一个节点 last = newNode;//修改队尾指针的指向 if (l == null) first = newNode;//如果原来还是空队列,那么对头指针也要修改下。 else l.next = newNode; //如果只是普通的队列中增加一个尾节点,那么改变下原来尾节点指向 size++; modCount++; } //第二个,将队列增加到指定index位置 public void add(int index, E element) { checkPositionIndex(index); if (index == size) linkLast(element); else linkBefore(element, node(index)); } //将e元素插入succ节点位置,这个操作在双链表中非常经典 void linkBefore(E e, Node<E> succ) { // assert succ != null; final Node<E> pred = succ.prev;//pred指向succ节点前一个节点 final Node<E> newNode = new Node<>(pred, e, succ); //新建一个节点,指向pred节点和succ节点 succ.prev = newNode;//使得succ节点的前驱节点属性prev指向新建节点, if (pred == null)//这里是完善新建节点和pred节点之间的关系 first = newNode; else pred.next = newNode; size++; modCount++; }
LinkedList还提供了其他的Deque接口增加方法:
add(int index, E element):在此列表中指定的位置插入指定的元素。 addAll(Collection<? extends E> c):添加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序。 addAll(int index, Collection<? extends E> c):将指定 collection 中的所有元素从指定位置开始插入此列表。 AddFirst(E e): 将指定元素插入此列表的开头。 addLast(E e): 将指定元素添加到此列表的结尾。
删除节点
最本质的方法提供一个节点引用然后删除这个节点 E unlink(Node<E> x) { // assert x != null; final E element = x.item; final Node<E> next = x.next;//x节点之前元素 final Node<E> prev = x.prev;//x节点之后元素 //建立next元素和prev元素之间的联系 if (prev == null) { first = next; } else { prev.next = next; x.prev = null; } if (next == null) { last = prev; } else { next.prev = prev; x.next = null; } x.item = null; size--; modCount++; return element; }
删除节点 public boolean remove(Object o) { if (o == null) { for (Node<E> x = first; x != null; x = x.next) { if (x.item == null) {//如果o为空时,寻找数据为null的元素引用 unlink(x);//删除x节点 return true; } } } else { for (Node<E> x = first; x != null; x = x.next) { if (o.equals(x.item)) {//如果o不为空,调用实例的equals方法判定是否相等 unlink(x); return true; } } } return false; }
其他的移除方法:
clear(): 从此列表中移除所有元素。 remove():获取并移除此列表的头(第一个元素)。 remove(int index):移除此列表中指定位置处的元素。 remove(Objec o):从此列表中移除首次出现的指定元素(如果存在)。 removeFirst():移除并返回此列表的第一个元素。 removeFirstOccurrence(Object o):从此列表中移除第一次出现的指定元素(从头部到尾部遍历列表时)。 removeLast():移除并返回此列表的最后一个元素。 removeLastOccurrence(Object o):从此列表中移除最后一次出现的指定元素(从头部到尾部遍历列表时)。
查询方法:
对于查找方法,无非就是迭代,比对,然后就是返回当前值。
get(int index):返回此列表中指定位置处的元素。 getFirst():返回此列表的第一个元素。 getLast():返回此列表的最后一个元素。 indexOf(Object o):返回此列表中首次出现的指定元素的索引,如果此列表中不包含该元素,则返回 -1。 lastIndexOf(Object o):返回此列表中最后出现的指定元素的索引,如果此列表中不包含该元素,则返回 -1。
使用LinkedList实现Stack效果
import java.util.LinkedList; public class MainClass { public static void main(String[] args) { StackL stack = new StackL(); for (int i = 0; i < 10; i++) stack.push(i); System.out.println(stack.top()); System.out.println(stack.top()); System.out.println(stack.pop()); System.out.println(stack.pop()); System.out.println(stack.pop()); } } class StackL { private LinkedList<Object> list = new LinkedList(); //插入一条数据 public void push(Object v) { list.addFirst(v); } //获取栈顶数据但是不删除 public Object top() { return list.getFirst(); } //弹出栈顶数据 public Object pop() { return list.removeFirst(); } }
将LinkedList当中队列来使用
import java.util.LinkedList; public class MainClass { public static void main(String[] args) { Queue queue = new Queue(); for (int i = 0; i < 10; i++) queue.put(Integer.toString(i)); while (!queue.isEmpty()) System.out.println(queue.get()); } } class Queue { private LinkedList<Object> list = new LinkedList(); public void put(Object v) { list.addFirst(v); } public Object get() { return list.removeLast(); } public boolean isEmpty() { return list.isEmpty(); } }
相关文章推荐
- Java基础知识强化之集合框架笔记29:使用LinkedList实现栈数据结构的集合代码(面试题)
- java 集合框架之LinkedList及ListIterator实现源码分析
- java 集合框架-利用LinkedList实现堆栈数据结构
- Java 集合的简单实现 (ArrayList & LinkedList & Queue & Stack)
- Java中集合框架,Collection接口、Set接口、List接口、Map接口,已经常用的它们的实现类,简单的JDK源码分析底层实现
- Java中集合框架,Collection接口、Set接口、List接口、Map接口,已经常用的它们的实现类,简单的JDK源码分析底层实现
- java中的集合框架LinkedList 简单用法
- 【java集合】自己实现简易的LinkedList
- JAVA简单理解累计框架 List、Set、Iterator、Map
- 学习笔记_毕向东 Java_集合框架_LinkedList 2014.7.22
- java-集合(4)-用LinkedList来实现栈/队列-ArrayList和LinkedList比较
- (9) java ---- 集合框架图 ArrayList,LinkedList,Vector各自的性能特点及区别
- 数据结构(Java语言)——LinkedList简单实现
- JAVA类集框架 List、Set、Iterator、Map的简单理解
- 自己实现LinkedList集合add,get,remove
- Java基础课程学习总结,使用LinkedList简单模拟队列数据结构和堆栈数据结构的实现
- Java集合7:LinkedList的实现原理
- 从零开始学Java自己利用接口和集合框架做的简单图书管理系统
- 黑马程序员--07.集合框架--04.List实现子类【ArrayList】【LinkedList】【Vector】
- Java基础之集合框架——使用真的的链表LinkedList<>(TryPolyLine)