jdk源码阅读之AbstractList
2017-12-16 20:06
369 查看
AbstractList继承了AbstractCollection, 实现了List接口。它提供了实现“随机访问”的List的一些方法。可以最大限度的减少实现随机访问的数据存储(如LinkList)的工作量,而如果需要实现随机访问的List(如ArrayList)则最好使用AbstractList。
AbstractList在Java Collection Framework中的位置如下图示,jdk中默认实现为ArrayList。
如果需要实现不可变List,则继承类必需实现
根据Collection接口规范,实现类也需要有一个无参的constructor。
其中
注意,如果指定的元素o为空,但该List不允许空元素时,上述两操作会抛出NullPointerException。
可以看到 Itr 只是简单实现了 Iterator 的 next, remove 方法。
SubList继承了AbstractList。
RandomAccessSubList用来标示可以“随机访问”的实现的子List。它实现了RandomAccess接口,继承了SubList。RandomAccess接口用来标示一个类是否可以随机按索引访问。比如遍历,实现了 RandomAccess 的集合使用
AbstractList的
所以SubList虽然自立门户,等到要干活时,使用的都是父类的方法,父类的数据。所以可以通过它来间接操作父 List。
AbstractList在Java Collection Framework中的位置如下图示,jdk中默认实现为ArrayList。
如果需要实现不可变List,则继承类必需实现
get(int),
size()两个方法。可变list则必需覆盖
set(int, E),
add(int,E),
remove(int)等方法。
根据Collection接口规范,实现类也需要有一个无参的constructor。
默认必须要实现类覆盖的方法
包括add(),
remove(),
set()和
addAll():
public boolean add(E e) { add(size(), e); return true; }
public void add(int index, E element) { throw new UnsupportedOperationException(); }
public E set(int index, E element) { throw new UnsupportedOperationException(); }
public E remove(int index) { throw new UnsupportedOperationException(); }
public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); boolean modified = false; for (E e : c) { add(index++, e); modified = true; } return modified; }
其中
rangeCheckForAdd(index)用来检查Index是否超出则抛出
IndexOutOfBoundsException。由于这里的
add()抛出
UnsupportedOperationException异常,所以实现类如果需要使用该方法,就必须复写
add()方法。此外,很多实现类复写该方法以提高执行效率。
已经实现的方法
包括indexOf()和
lastIndexOf(),
clear():
public int indexOf(Object o) { ListIterator<E> it = listIterator(); if (o==null) { while (it.hasNext()) if (it.next()==null) return it.previousIndex(); } else { while (it.hasNext()) if (o.equals(it.next())) return it.previousIndex(); } return -1; }
public int lastIndexOf(Object o) { ListIterator<E> it = listIterator(size()); if (o==null) { while (it.hasPrevious()) if (it.previous()==null) return it.nextIndex(); } else { while (it.hasPrevious()) if (o.equals(it.previous())) return it.nextIndex(); } return -1; }
注意,如果指定的元素o为空,但该List不允许空元素时,上述两操作会抛出NullPointerException。
public void clear() { removeRange(0, size()); }
protected void removeRange(int fromIndex, int toIndex) { ListIterator<E> it = listIterator(fromIndex); for (int i=0, n=toIndex-fromIndex; i<n; i++) { it.next(); it.remove(); } }
实现的迭代器接口
public Iterator<E> iterator() { return new Itr(); }
public ListIterator<E> listIterator() { return listIterator(0); }
public ListIterator<E> listIterator(final int index) { rangeCheckForAdd(index); return new ListItr(index); }
内置迭代器
AbstractList 内部已经提供了 Iterator, ListIterator 迭代器的实现类,分别为 Itr, ListItr, 不需要实现类重新提供。Iterator迭代器
源码如下:private class Itr implements Iterator<E> { //游标,下一次调用(迭代器)时返回元素的索引。 int cursor = 0; //上一次调用时的元素的索引。如果调用remove()方法,则该值回复重设成-1 int lastRet = -1; //用来判断是否发生并发操作的标示,如果这两个值不一致,就会报错 int expectedModCount = modCount; public boolean hasNext() { return cursor != size(); } public E next() { checkForComodification(); try { int i = cursor; E next = get(i); lastRet = i; cursor = i + 1; return next; } catch (IndexOutOfBoundsException e) { checkForComodification(); throw new NoSuchElementException(); } } public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { AbstractList.this.remove(lastRet); if (lastRet < cursor) cursor--; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException e) { throw new ConcurrentModificationException(); } } //时刻检查是否有并发修改操作 final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
可以看到 Itr 只是简单实现了 Iterator 的 next, remove 方法。
ListIterator
//ListItr是Itr的增强版,在Itr基础上多了向前和set操作。 private class ListItr extends Itr implements ListIterator<E> { ListItr(int index) { super(); cursor = index; } public boolean hasPrevious() { return cursor != 0; } public int nextIndex() { return cursor; } public int previousIndex() { return cursor - 1; } @SuppressWarnings("unchecked") public E previous() { checkForComodification(); //获取游标前面一位元素 int i = cursor - 1; if (i < 0) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i; return (E) elementData[lastRet = i]; } public void set(E e) { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.set(lastRet, e); } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } public void add(E e) { checkForComodification(); try { int i = cursor; ArrayList.this.add(i, e); cursor = i + 1; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } }
SubList与RandomAccessSubList
用来返回指定索引(fromIndex和toIndex, 前闭后开)之间的部分视图。如果fromIndex和toIndex相等,返回长度为0的list。返回的List是原来List中的一部分的视图的引用。任何对返回的subList的修改都将同步到原List中,反之亦然。SubList继承了AbstractList。
RandomAccessSubList用来标示可以“随机访问”的实现的子List。它实现了RandomAccess接口,继承了SubList。RandomAccess接口用来标示一个类是否可以随机按索引访问。比如遍历,实现了 RandomAccess 的集合使用
get():
for (int i=0, n=list.size(); i < n; i++) list.get(i);
AbstractList的
subList()方法如下:
public List<E> subList(int fromIndex, int toIndex) { return (this instanceof RandomAccess ? new RandomAccessSubList<>(this, fromIndex, toIndex) : new SubList<>(this, fromIndex, toIndex)); }
SubList的源码
class SubList<E> extends AbstractList<E> { private final AbstractList<E> l; private final int offset; private int size; //构造参数: //list :父 List //fromIndex : 从父 List 中开始的位置 //toIndex : 在父 List 中哪里结束 SubList(AbstractList<E> list, int fromIndex, int toIndex) { if (fromIndex < 0) throw new IndexOutOfBoundsException("fromIndex = " + fromIndex); if (toIndex > list.size()) throw new IndexOutOfBoundsException("toIndex = " + toIndex); if (fromIndex > toIndex) throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")"); l = list; offset = fromIndex; size = toIndex - fromIndex; //和父类使用同一个 modCount this.modCount = l.modCount; } //使用父类的 set() public E set(int index, E element) { rangeCheck(index); checkForComodification(); return l.set(index+offset, element); } //使用父类的 get() public E get(int index) { rangeCheck(index); checkForComodification(); return l.get(index+offset); } public int size() { checkForComodification(); return size; } //根据子 List 开始的位置,加上偏移量,直接在父List 上进行添加 public void add(int index, E element) { rangeCheckForAdd(index); checkForComodification(); l.add(index+offset, element); this.modCount = l.modCount; size++; } //根据子 List 开始的位置,加上偏移量,直接在父 List 上进行删除 public E remove(int index) { rangeCheck(index); checkForComodification(); E result = l.remove(index+offset); this.modCount = l.modCount; size--; return result; } //调用父类的 局部删除 protected void removeRange(int fromIndex, int toIndex) { checkForComodification(); l.removeRange(fromIndex+offset, toIndex+offset); this.modCount = l.modCount; size -= (toIndex-fromIndex); } public boolean addAll(Collection<? extends E> c) { return addAll(size, c); } //还是使用的父类 addAll() public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); int cSize = c.size(); if (cSize==0) return false; checkForComodification(); l.addAll(offset+index, c); this.modCount = l.modCount; size += cSize; return true; } public Iterator<E> iterator() { return listIterator(); } public ListIterator<E> listIterator(final int index) { checkForComodification(); rangeCheckForAdd(index); return new ListIterator<E>() { private final ListIterator<E> i = l.listIterator(index+offset); public boolean hasNext() { return nextIndex() < size; } public E next() { if (hasNext()) return i.next(); else throw new NoSuchElementException(); } public boolean hasPrevious() { return previousIndex() >= 0; } public E previous() { if (hasPrevious()) return i.previous(); else throw new NoSuchElementException(); } public int nextIndex() { return i.nextIndex() - offset; } public int previousIndex() { return i.previousIndex() - offset; } public void remove() { i.remove(); SubList.this.modCount = l.modCount; size--; } public void set(E e) { i.set(e); } public void add(E e) { i.add(e); SubList.this.modCount = l.modCount; size++; } }; } public List<E> subList(int fromIndex, int toIndex) { return new SubList<>(this, fromIndex, toIndex); } private void rangeCheck(int index) { if (index < 0 || index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } private void rangeCheckForAdd(int index) { if (index < 0 || index > size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } private String outOfBoundsMsg(int index) { return "Index: "+index+", Size: "+size; } private void checkForComodification() { if (this.modCount != l.modCount) throw new ConcurrentModificationException(); } }
所以SubList虽然自立门户,等到要干活时,使用的都是父类的方法,父类的数据。所以可以通过它来间接操作父 List。
相关文章推荐
- JDK源码阅读之List和AbstractSequentialList
- LinkedList源码阅读(JDK 8)
- jdk源码阅读--(LinkedList)
- JDK源码(1.7) -- java.util.AbstractList<E>
- jdk源码阅读笔记-AbstractStringBuilder
- JDK源码阅读——LinkedList
- 【JDK1.8】JDK1.8集合源码阅读——LinkedList
- JDK源码阅读之LinkedList
- JDK源码阅读——ArrayList\LinkedList
- JDK源码阅读之AbstractMap
- 【JDK源码阅读4-util】Collection-List---LinkedList
- JDK 1.7源码阅读笔记(三)集合类之LinkedList
- JDK源码阅读LinkedList
- 【JDK源码阅读2-util】Collection-List
- JDK源码阅读之List接口
- 【JDK源码阅读5-util】Collection-List---Vector
- Redis源码阅读笔记—adlist
- jdk源码阅读Collection详解
- JDK源码阅读(一) ArrayList
- java源码解读之LinkedList------jdk 1.7