集合专题笔记之LinkedList
1)LinkedList底层维护了一个双向链表.
2)LinkedList中维护了两个属性first和last分别指向 首节点和尾节点
3)每个节点(Node对象),里面又维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点。最终实现双向链表.
4)所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高
5)模拟一个简单的双向链表
模拟双向链表
加深对双向链表数据结构理解
package com.itheima.LindedList;
public class LinkedList01 {
public static void main(String[] args) {
Node chenhm = new Node("chenhm");
Node tom = new Node("tom");
Node lia = new Node("lia");
//连接三个结点,形成双向链表
//chenhm->tom -> lia
chenhm.next = tom;
tom.next = lia;
//lia ->tom -> chenhm
lia.pre = tom;
tom.pre = lia;
//让first引用指向chenhm,就是双向链表的头结点
Node first = chenhm;
//让last引用指向lia,就是双向链表的尾结点
Node last = lia;
//演示,从头到尾进行遍历
System.out.println("===从头到尾进行遍历===");
while (true) {
if (first == null) {
break;
}
//输出first节点
System.out.println(first);
first = first.next;
}
//演示链表的添加对象/数据,是多么的方便
//要求,是在tom---------插入一个对象 smith
Node smith = new Node("smith");
//下面就把 smith 加入到双向链表了
smith.next = lia;
smith.pre = tom;
lia.pre = smith;
tom.next = smith;
first = chenhm;
last = lia;
while (true) {
if (first == null) {
break;
}
//输出first节点
System.out.println(first);
first = first.next;
}
}
}
class Node {
public Object item;
public Node next;
public Node pre;
public Node(Object name) {
this.item = name;
}
@Override
public String toString() {
return "Node name=" + item;
}
}
LinkedList源码阅读
LinkedList linkedList = new LinkedList();
// 空的构造方法
public LinkedList(){}
//这时 linkeList的属性first =null last = null
// 执行add方法
public boolean add(E e) {
linkLast(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++;
}
//方法linkedList.remove();
public E remove() {
return removeFirst();
}
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
//执行 unlinkFirst,将 f 指向的双向链表的第一个结点
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
final E element = f.item;
final Node<E> next = f.next;
f.item = null;
f.next = null; // help GC
first = next;
if (next == null)
last = null;
else
next.prev = null;
size--;
modCount++;
return element;
}
ArrayList 和 LinkedList比较
底层结构 | 增删的效率 | 改查的效率 | |
---|---|---|---|
ArrayList | 可变数组 | 较低数组扩容 | 较高 |
LinkedList | 双向链表 | 较高,通过链表追加 | 较低 |
如何选择ArrayList和LinkedList:
1)如果我们改查的操作多,选择ArrayList
2)如果我们增删的操作多,选择LinkedList
3)一般来说,在程序中,80%-90%都是查询,因此大部分情况下会选择ArrayList4)在一个项目中,根据业务灵活选择,也可能这样,一个模块使用的是ArrayList,另外一个模块是LinkedList.