在这里我们介绍一下最简单的链表LinkedList;
看一下add()方法:
public booleanadd(E e) {
linkLast(e);return true;
}
voidlinkLast(E e) {final Node l =last;final Node newNode = new Node<>(l, e, null);
last=newNode;if (l == null)
first=newNode;elsel.next=newNode;
size++;
modCount++;
}
add原理就是:
1.首先获取链表最后一个节点。
2.把新节点插入到最后一个节点之后。
3.linkedList的last属性重新指向最后一个节点。
4.如果这个节点是第一个节点,之前没有节点,那么将linkedList的first的属性指向新节点;如果不是,则将上一个节点的next属性指向该节点。
使用LinkedList构建先进先出队列:
offer()方法入队:使用add()方法插入节点在最后。
public booleanoffer(E e) {returnadd(e);
}
poll()方法出队:从链表表头开始移出队列
publicE poll() {final Node f =first;return (f == null) ? null: unlinkFirst(f);
}
使用LinkedList构建后进先出队列:
push()方法入队:插入节点在first
public voidaddFirst(E e) {
linkFirst(e);
}private voidlinkFirst(E e) {final Node f =first;final Node newNode = new Node<>(null, e, f);
first=newNode;if (f == null)
last=newNode;elsef.prev=newNode;
size++;
modCount++;
}
pop()方法出队:从链表表头开始移出队列
publicE pop() {returnremoveFirst();
}publicE removeFirst() {final Node f =first;if (f == null)throw newNoSuchElementException();returnunlinkFirst(f);
}private E unlinkFirst(Nodef) {//assert f == first && f != null;
final E element =f.item;final Node next =f.next;
f.item= null;
f.next= null; //help GC
first =next;if (next == null)
last= null;elsenext.prev= null;
size--;
modCount++;returnelement;
}
最后需要注意的是:LinkedList是线程不安全的,如果需要线程安全那么请使用synchronized加锁,或者使用vector,或者使用java.util.concurrent包。
如果需要线程遍历List的时候,避免出现ConcurrentModificationException异常,那么有3种解决方式。
1.遍历List的使用synchronized加锁;
2.使用java.util.concurrent包下面的CopyOnWriteArrayList,每次使用List时实际上都是使用的List副本。
3.使用Jdk8中foreach方法,不过该方法只接受lambda表达式
list.forEach(item ->{
System.out.println("遍历元素:" +item);
try{
Thread.sleep(1000);
}catch(InterruptedException e) {
e.printStackTrace();
}
});