在这里我们介绍一下最简单的链表linkedlist;
看一下add()方法:
public boolean add(e e) {
linklast(e); return true;
}
void linklast(e e) {
final node l = last;
final node newnode = new node(l, e, null);
last = newnode;
if (l == null)
first = newnode;
else
l.next = newnode;
size++;
modcount++;
}
add原理就是:
1.首先获取链表最后一个节点。
2.把新节点插入到最后一个节点之后。
3.linkedlist的last属性重新指向最后一个节点。
4.如果这个节点是第一个节点,之前没有节点,那么将linkedlist的first的属性指向新节点;如果不是,则将上一个节点的next属性指向该节点。
使用linkedlist构建先进先出队列:
offer()方法入队:使用add()方法插入节点在最后。
public boolean offer(e e) {
return add(e);
}
poll()方法出队:从链表表头开始移出队列
public e poll() {
final node f = first;
return (f == null) ? null : unlinkfirst(f);
}
使用linkedlist构建后进先出队列:
push()方法入队:插入节点在first
public void addfirst(e e) {
linkfirst(e);
}
private void linkfirst(e e) {
final node f = first;
final node newnode = new node(null, e, f);
first = newnode;
if (f == null)
last = newnode;
else
f.prev = newnode;
size++;
modcount++;
}
pop()方法出队:从链表表头开始移出队列
public e pop() {
return removefirst();
}
public e removefirst() {
final node f = first;
if (f == null)
throw new nosuchelementexception();
return unlinkfirst(f);
}
private e unlinkfirst(node f) {
// 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;
else
next.prev = null;
size--;
modcount++;
return element;
}
最后需要注意的是: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();
}
});
