赞
踩
Java
的集合与数据结构的联系息息相关,例如Java
中的LinkedList
集合底层实现采用的双向链表。Java
实现单链表如下:
public class LinkedList<E> { /** * 头结点和链表长度 */ private Node head; private int size; /** * 内部类,用于创建链表结点 */ private class Node { private E item; private Node next; public Node() { } public Node(E item) { this.item = item; } public Node(E item, Node next) { this.item = item; this.next = next; } } /** * 链表初始化 */ public LinkedList() { this.head = new Node(); this.size = 0; } /** * 链表判空 * @return */ public boolean isEmpty() { return this.size == 0; } /** * 链表头部插入元素 * @param e */ public void addFirst(E e) { add(e, 0); } /** * 链表尾部插入元素 * @param e */ public void add(E e) { add(e, size); } /** * 链表指定位置插入元素 * @param e * @param index */ public void add(E e, int index) { if (index < 0 || index > size) throw new IllegalArgumentException("插入位置错误!"); if (index == 0 && this.size == 0) { Node addNode = new Node(e, null); this.head.next = addNode; this.size++; return; } Node node = this.head; for (int i = 0; i < index; i++) { node = node.next; } Node addNode = new Node(e, null); addNode.next = node.next; node.next = addNode; this.size++; } /** * 删除链表头部元素 */ public void removeFirst() { remove(0); } /** * 删除链表尾部元素 */ public void remove() { if (this.isEmpty()) { throw new IllegalArgumentException("当前链表为空!"); } remove(size - 1); } /** * 删除链表指定位置元素 * @param index */ public void remove(int index) { if (index < 0 || index > size - 1) throw new IllegalArgumentException("删除位置错误!"); Node node = this.head; for (int i = 0; i < index; i++) { node = node.next; } Node nextNode = node.next.next; node.next = nextNode; this.size--; } /** * 链表是否包含元素e * @param e * @return */ public boolean contains(E e) { Node node = this.head; for (int i = 0; i < size; i++) { node = node.next; if (node.item == e) return true; } return false; } /** * 打印链表 */ public void printLinedList() { StringBuilder sb = new StringBuilder(); Node node = this.head; for (int i = 0; i < size; i++) { node = node.next; sb.append(node.item + " "); } System.out.println("{" + sb.toString().trim() + "}"); } public static void main(String[] args) { LinkedList<Integer> linkedList = new LinkedList<>(); for (int i = 0; i < 10; i++) { if (i % 2 == 0) linkedList.add(i, i); else linkedList.add(i); } linkedList.printLinedList(); linkedList.removeFirst(); linkedList.printLinedList(); linkedList.remove(); linkedList.printLinedList(); linkedList.remove(5); linkedList.printLinedList(); System.out.println(linkedList.contains(5)); } }
关键点:
Java
中的LinkedList
集合同时实现了List
接口和Deque
接口,也即LinkedList
可以看作一个顺序容器,又可以看作一个队列(Queue
)或栈(Stack
)。可以任意添加元素(允许重复),包括NULL
值。线程不安全,且没有实现同步。下面来看看LinkdeList的源码:
transient int size = 0; /** * 指向第一个节点的指针。 */ transient Node<E> first; /** * 指向最后一个节点的指针。 */ transient Node<E> last; /** * Node类定义 */ 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; } } /** * 构造一个空列表。 */ public LinkedList() { }
同样定义了一个Node
结点,并且分别定义了指向链表头部和尾部的指针。其内部可以采用分别实现了头插法和尾插法:
/** * 链接e作为第一个元素。 */ private void linkFirst(E e) { final Node<E> f = first; final Node<E> newNode = new Node<>(null, e, f); first = newNode; if (f == null) last = newNode; else f.prev = newNode; size++; modCount++; } /** * 将指定的元素插入到此列表的开头。 * * @param e 要添加的元素 */ public void addFirst(E e) { linkFirst(e); } /** * 链接e作为最后一个元素。 */ 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++; } /** * 将指定的元素追加到此列表的末尾。 * * 这个方法相当于添加。 * * @param e 要添加的元素 */ public void addLast(E e) { linkLast(e); } /** * 将指定的元素追加到此列表的末尾。 * 这个方法相当于addLast。 * * @param e 要追加到此列表的元素 * @return {@code true} (as specified by {@link Collection#add}) */ public boolean add(E e) { linkLast(e); return true; }
注:它这个实现没有空出一个多余的头结点,值得学习。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。