我们经常在代码中使用到List 、Set 、 Map ,也粗略看过一些实现类的源码解析。现在去看下抽象类集合中的方法与具体实现类有哪些不同。
public abstract class AbstractSet extends AbstractCollection implements Set
public abstract class AbstractList extends AbstractCollection implements List
public abstract class AbstractMap implements Map
由上述代码可以看到 AbstractSet与 AbstractList 都继承了 AbstractCollection 然后去实现自己的方法 AbstractMap 单独实现Map的方法
AbstractSet 只有较少的方法 除空构造函数之外 ,重写了Object 类 equal() 与 hashCode()
AbstractList 重写了较多的方法,其中大部分都是经常使用到的 包含 add(E) get(int) set(int,E) remove(int) indexOf(Object) clear() addAll(int Collection) 等等 其中add() remove() 等方法种其实并无具体实现,标注其实现类应抛出 UnsupportedOperationException()
/**
* {@inheritDoc}
*
* This implementation always throws an
* {@code UnsupportedOperationException}.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
在去看ArrayList 源码时候,追溯扩展列表长度时偶然发现一个好玩的事情。 ensureCapacityInternal(int ) 逐步追溯发现ensureExplicitCapacity()中第一行为 操作modCount ,这个属性ArrayList 并不存在,存在于AbstractList中,且对其的注释准确解释了以前不理解的某些异常。
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* The number of times this list has been structurally modified.
* Structural modifications are those that change the size of the
* list, or otherwise perturb it in such a fashion that iterations in
* progress may yield incorrect results.
*
* This field is used by the iterator and list iterator implementation
* returned by the {@code iterator} and {@code listIterator} methods.
* If the value of this field changes unexpectedly, the iterator (or list
* iterator) will throw a {@code ConcurrentModificationException} in
* response to the {@code next}, {@code remove}, {@code previous},
* {@code set} or {@code add} operations. This provides
* fail-fast behavior, rather than non-deterministic behavior in
* the face of concurrent modification during iteration.
*
*
Use of this field by subclasses is optional. If a subclass
* wishes to provide fail-fast iterators (and list iterators), then it
* merely has to increment this field in its {@code add(int, E)} and
* {@code remove(int)} methods (and any other methods that it overrides
* that result in structural modifications to the list). A single call to
* {@code add(int, E)} or {@code remove(int)} must add no more than
* one to this field, or the iterators (and list iterators) will throw
* bogus {@code ConcurrentModificationExceptions}. If an implementation
* does not wish to provide fail-fast iterators, this field may be
* ignored.
*/
protected transient int modCount = 0;
简单的理解modCount这个属性就是 记录当前List 操作过的次数,如果更改列表大小或者其他方式更新列表进度 就会导致异常。如果需要提供快速失败的方法,就在add() 和 remove() 方法 中对列表进行结构修改,会抛出ConcurrentModificationExceptions 。
模拟一次, 在列表迭代中,如果对列表进行删除会首先触发ensureExplicitCapacity()modCount ++ ,在进行下次迭代时候触发checkForComodification() 比对expectedModCount 不同则抛出异常
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
/**
* The modCount value that the iterator believes that the backing
* List should have. If this expectation is violated, the iterator
* has detected concurrent modification.
*/
int expectedModCount = modCount;
在此之上,AbstractList中存在了几个内部类,用于迭代展示获取等情况,具体没有搞明白下次具体分析下。
AbstractMap 中实现的方法与AbstractList 基本相同,其中不同的只是关于Map 的键值映射关系,例如 KeySet() values() 等
在其中, remove方法中存在 Iterator 迭代其进行寻找并进行删除的方法, 这个迭代器 在AbstractList中也被用到,不过封装于内部实现类中 ListIterator 封装了三层。。。
public V remove(Object key) {
Iterator> i = entrySet().iterator();
Entry correctEntry = null;
if (key==null) {
while (correctEntry==null && i.hasNext()) {
Entry e = i.next();
if (e.getKey()==null)
correctEntry = e;
}
} else {
while (correctEntry==null && i.hasNext()) {
Entry e = i.next();
if (key.equals(e.getKey()))
correctEntry = e;
}
}
V oldValue = null;
if (correctEntry !=null) {
oldValue = correctEntry.getValue();
i.remove();
}
return oldValue;
}
/**
* {@inheritDoc}
*
* This implementation returns a straightforward implementation of the
* {@code ListIterator} interface that extends the implementation of the
* {@code Iterator} interface returned by the {@code iterator()} method.
* The {@code ListIterator} implementation relies on the backing list's
* {@code get(int)}, {@code set(int, E)}, {@code add(int, E)}
* and {@code remove(int)} methods.
*
*/
public ListIterator listIterator(final int index) {
rangeCheckForAdd(index);
return new ListItr(index);
}
private class Itr implements Iterator {
//do something
XXX
}
private class ListItr extends Itr implements ListIterator{
XXX
}