我们经常在代码中使用到List 、Set 、 Map ,也粗略看过一些实现类的源码解析。现在去看下抽象类集合中的方法与具体实现类有哪些不同。
public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E>
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>
public abstract class AbstractMap<K,V> implements Map<K,V>
由上述代码可以看到 AbstractSet与 AbstractList 都继承了 AbstractCollection 然后去实现自己的方法 AbstractMap 单独实现Map的方法
AbstractList .png
AbstractSet.png
AbstractSet 只有较少的方法 除空构造函数之外 ,重写了Object 类 equal() 与 hashCode()
AbstractSetFunction.png
AbstractList 重写了较多的方法,其中大部分都是经常使用到的 包含 add(E) get(int) set(int,E) remove(int) indexOf(Object) clear() addAll(int Collection) 等等 其中add() remove() 等方法种其实并无具体实现,标注其实现类应抛出 UnsupportedOperationException()
/**
* {@inheritDoc}
*
* <p>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();
}
AbstractListFunction.png
在去看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 <i>structurally modified</i>.
* 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.
*
* <p>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
* <i>fail-fast</i> behavior, rather than non-deterministic behavior in
* the face of concurrent modification during iteration.
*
* <p><b>Use of this field by subclasses is optional.</b> 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中存在了几个内部类,用于迭代展示获取等情况,具体没有搞明白下次具体分析下。
AbstractMapFunction.pngAbstractMap 中实现的方法与AbstractList 基本相同,其中不同的只是关于Map 的键值映射关系,例如 KeySet() values() 等
在其中, remove方法中存在 Iterator 迭代其进行寻找并进行删除的方法, 这个迭代器 在AbstractList中也被用到,不过封装于内部实现类中 ListIterator 封装了三层。。。
public V remove(Object key) {
Iterator<Entry<K,V>> i = entrySet().iterator();
Entry<K,V> correctEntry = null;
if (key==null) {
while (correctEntry==null && i.hasNext()) {
Entry<K,V> e = i.next();
if (e.getKey()==null)
correctEntry = e;
}
} else {
while (correctEntry==null && i.hasNext()) {
Entry<K,V> e = i.next();
if (key.equals(e.getKey()))
correctEntry = e;
}
}
V oldValue = null;
if (correctEntry !=null) {
oldValue = correctEntry.getValue();
i.remove();
}
return oldValue;
}
/**
* {@inheritDoc}
*
* <p>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<E> listIterator(final int index) {
rangeCheckForAdd(index);
return new ListItr(index);
}
private class Itr implements Iterator<E> {
//do something
XXX
}
private class ListItr extends Itr implements ListIterator<E>{
XXX
}
网友评论