其他
面试官让我把源码捋一遍,捋的我头皮发麻,但还是让我回家等消息了
点击上方 Java后端,选择 设为星标
优质文章,及时送达
我:对啊,昨天复习了一下基础知识,看了一下集合相关的内容。
面试官:好,不错,那今天就聊聊集合吧,你先讲讲 ArrayList 的原理和用法吧。这个接口用的比较多。
我:这个接口用的老熟了,LinkedList的继承关系是这样的:
面试官:行吧,有没有读过 LinkedList 的源码?
LinkedList有两个构造函数:① 无参;②参数为集合。
举个栗子:
//默认创建一个LinkedList
LinkedList<String> l1 = new LinkedList<>();
//创建一个将其他类型集合中的数据化为己用的LinkedList
LinkedList<String> l2 = new LinkedList<>(new HashSet<>());
transient int size = 0;
/**
* Pointer to first node.
* Invariant: (first == null && last == null) ||
* (first.prev == null && first.item != null)
*/
transient Node<E> first;
/**
* Pointer to last node.
* Invariant: (first == null && last == null) ||
* (last.next == null && last.item != null)
*/
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;
}
}
LinkedList无参构造函数
public LinkedList() {}
LinkedList有参构造函数——入参类型为集合类
/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
* ......
*/
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
怎么使用LinkedList?
get(int index)
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
checkElementIndex()
private void checkElementIndex(int index) {
if (!isElementIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private boolean isElementIndex(int index) {
return index >= 0 && index < size;
}
node()
Node<E> node(int index) {
if (index < (size >> 1)) {
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;
}
}
add(E e)
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菜单集合中添加"小笼包",则这个节点既是首节点,也是尾节点: 假如我们要向非空LinkedList菜单集合中添加“奶黄包”,则这个节点就是尾节点last,且下一个节点next为null。 加入通过add(1, “叉烧包”)这种方式将元素添加到LinkedList中,则需要找到这个下标代表的元素,并将这个元素以及该元素后的节点作为"叉烧包"节点的前后节点。
public void add(int index, E element) {
checkPositionIndex(index);
if (index == size)
linkLast(element);
else
linkBefore(element, node(index));
}
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++;
}
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
final Node<E> pred = succ.prev;
final Node<E> newNode = new Node<>(pred, e, succ);
succ.prev = newNode;
if (pred == null)
first = newNode;
else
pred.next = newNode;
size++;
modCount++;
}
remove(Object o)和remove(int index)
remove(Object o)
public boolean remove(Object o) {
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) {
unlink(x);
return true;
}
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
E unlink(Node<E> x) {
final E element = x.item;
final Node<E> next = x.next;
final Node<E> prev = x.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;
}
remove(int index)
public E remove(int index) {
checkElementIndex(index);
return unlink(node(index));
}
LinkedList遍历
普通for循环 增强for循环 Iterator迭代器
普通for循环
public static void listForNormal(LinkedList<Integer> list){
// 记录开始时间
long start = System.currentTimeMillis();
int size = list.size();
for(int i=0;i<size;i++){
list.get(i);
}
//记录用时
long interval = System.currentTimeMillis() - start;
System.out.println("listForNormal:"+interval+" ms");
}
增强for循环遍历LinkedList
public static void listByStrengThenFor(LinkedList<Integer> list){
// 记录开始时间
long start = System.currentTimeMillis();
for (Integer i : list) { }
// 记录用时
long interval = System.currentTimeMillis() - start;
System.out.println("listByStrengThenFor:" + interval + " ms");
}
迭代器遍历LinkedList
public static void listByIterator(LinkedList<Integer> list){
// 记录开始时间
long start = System.currentTimeMillis();
int size = list.size();
for(Iterator iter = list.iterator(); iter.hasNext();){
iter.next();
}
//记录用时
long interval = System.currentTimeMillis() - start;
System.out.println("listForNormal:"+interval+" ms");
}
listByNormalFor:1046 ms
listByStrengThenFor:6 ms
listByIterator:3 ms
private static void listByIterator(LinkedList<Integer> var0) {
long var1 = System.currentTimeMillis();
Iterator var3 = var0.iterator();
while(var3.hasNext()) {
var3.next();
}
long var5 = System.currentTimeMillis() - var1;
System.out.println("listByIterator:" + var5 + " ms");
}
我:好的。。说实话,捋的我头皮发麻。。
参考资料:
Java集合 LinkedList的原理及使用