总的继承关系
- java.lang.Object
- java.util.AbstractCollection<E> (implements java.util.Collection<E>)
- java.util.AbstractList<E> (implements java.util.List<E>)
- java.util.AbstractSequentialList<E>
- java.util.LinkedList<E> (implements java.lang.Cloneable, java.util.Deque<E>, java.util.List<E>, java.io.Serializable)
- java.util.ArrayList<E> (implements java.lang.Cloneable, java.util.List<E>, java.util.RandomAccess, java.io.Serializable)
- java.util.AbstractSequentialList<E>
- java.util.AbstractList<E> (implements java.util.List<E>)
- java.util.AbstractCollection<E> (implements java.util.Collection<E>)
AbstractCollection主要方法有:
add() addAll() contain() ContainAll() remove[All]() size()isEmpty() clear() toArray() 还有一个从
Iteratorable继承的iterator()
注意 :在抽象类阶段 add方法是不支持的 按理说其他的方法也都不支持,但是实际上是都支持,方法至少是有内容的。以Remove为例:
public boolean remove(Object o) {
Iterator<E> e = iterator();
if (o==null) {
while (e.hasNext()) {
<h2> if (e.next()==null) {</h2> e.remove();
return true;
}
}
} else {
while (e.hasNext()) {
if (o.equals(e.next())) {
e.remove();
return true;
}
}
}
return false;
}
总结起来有一个特点就是,凡是能使用本类的方法(比如例子中的iterator()方法)来实现的,就使用本类的方法实现,不能实现的如Add()
public boolean add(E e) {
throw new UnsupportedOperationException();
}
这是一个RuntimeException
AbstractList<E>增加的方法有:
- get() 这是一个抽象方法,在AbstractSequentialList<E>也没有实现,这里用到一个设计模式:模板模式,把方法实现延后。
- indexOf()lastIndexof()这两个方法效率不高,都是从头往后搜索
- 最主要的是增加了两个内部类: private class Itr implements Iterator<E>和private class ListItr extends Itr implements ListIterator<E> 这里用到设计模式:迭代器模式内部类便于操作LIst,但是这两个内部类对LIst的操作都是通过AbstractLIst内部方法来实现的例如get()Remove()这两个方法都不抛出 UnsupportedOperationException
- 还增加了一个私有成员:modCount 用来记录LIst的修改次数,防止出现多个LIstiterator同时操作AbstractList带来的安全性问题。
- public boolean addAll(int index, Collection<? extends E> c)的参数使用了通配符? extends的意思是只能读取,不能写入
AbstractSequentialList<E>
分析三个方法:Add() Remove() set() get()
查看源代码 这三个方法都是利用 LIstIterator实现的,(以Add()为例)但是LIstIterator是继承自AbstractList的,且LIstIterator没有实现????
public void add(int index, E element) {
try {
listIterator(index).add(element);
} catch (NoSuchElementException exc) {
throw new IndexOutOfBoundsException("Index: "+index);
}
}
public void add(E e) {
checkForComodification();
try {
AbstractList.this.add(cursor++, e);//这里有调用了AbstractList的Add()方法,而这个方法是抽象方法,不能使用的。但是考虑到AbstractSequenceList也是一个抽象方法不能实例化,那么调用Add()方法是完全符合语法的
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
也就是说着形成了一个循环,循环的死结在Add方法是抽象的。
LinkedList<E>
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable这个类既继承了AbstractSequentialList<E>又实现了 List<E>这里面有很多是重复的,但是,凡是接口要求实现的方法,在AbstractSequentialList<E>中都有,且都继承到了LinkedList,这是 1. 接口 中的成员变量默认都是public、static、final类型的,必须被显式初始化2. 接口 中的 方法 默认都是public、abstract类型的。
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable这个类既继承了AbstractSequentialList<E>又实现了 List<E>这里面有很多是重复的,但是,凡是接口要求实现的方法,在AbstractSequentialList<E>中都有,且都继承到了LinkedList,这是 1. 接口 中的成员变量默认都是public、static、final类型的,必须被显式初始化2. 接口 中的 方法 默认都是public、abstract类型的。
增加了一个静态内部类
private static class Entry<E> {
E element;
Entry<E> next;
Entry<E> previous;
Entry(E element, Entry<E> next, Entry<E> previous) {
this.element = element;
this.next = next;
this.previous = previous;
}
}
本质是一个数据结构
重载了内部类ListItr,这个内部类更有针对性,以next为例:
private class ListItr implements ListIterator<E> {
private Entry<E> lastReturned = header;
private Entry<E> next;//相当于LIstItr已经拿到了存储对象
private int nextIndex;
public E next() {
checkForComodification();
if (nextIndex == size)
throw new NoSuchElementException();
lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.element;//直接在存储对象上操作
}
再看Add()方法,他还是利用LInkedLIst内部的Add() 方法
public void add(E e) {
checkForComodification();
lastReturned = header;
addBefore(e, next);//这个方法的实现是利用<span style="color: rgb(51, 51, 51); font-family: arial;font-size:12px; line-height: 20.020000457763672px;">LInkedLIst的</span><span style="font-family: arial;">addBefore</span>
nextIndex++;
expectedModCount++;
}
注意:此处对linkedList的修改性操作本身还都是 linkedList内部方法来实现,而不是迭代器来负责
private Entry<E> addBefore(E e, Entry<E> entry) {
Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
newEntry.previous.next = newEntry;
newEntry.next.previous = newEntry;
size++;
modCount++;
return newEntry;
}
两个相关的接口:
- java.util.Iterator<E>
- java.util.ListIterator<E>