JDK7集合框架源码学习-ArrayList(4)SubList

源码镇楼

  1. public List<E> subList(int fromIndex, int toIndex) {  
  2.     subListRangeCheck(fromIndex, toIndex, size);  
  3.     return new SubList(this0, fromIndex, toIndex);  
  4. }  
  5.   
  6. static void subListRangeCheck(int fromIndex, int toIndex, int size) {  
  7.     if (fromIndex < 0)  
  8.         throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);  
  9.     if (toIndex > size)  
  10.         throw new IndexOutOfBoundsException("toIndex = " + toIndex);  
  11.     if (fromIndex > toIndex)  
  12.         throw new IllegalArgumentException("fromIndex(" + fromIndex +  
  13.                                            ") > toIndex(" + toIndex + ")");  
  14. }  
  15.   
  16. private class SubList extends AbstractList<E> implements RandomAccess {  
  17.     private final AbstractList<E> parent;  
  18.     private final int parentOffset;  
  19.     private final int offset;  
  20.     int size;  
  21.   
  22.     SubList(AbstractList<E> parent,  
  23.             int offset, int fromIndex, int toIndex) {  
  24.         this.parent = parent;  
  25.         this.parentOffset = fromIndex;  
  26.         this.offset = offset + fromIndex;  
  27.         this.size = toIndex - fromIndex;  
  28.         this.modCount = ArrayList.this.modCount;  
  29.     }  
  30.   
  31.     public E set(int index, E e) {  
  32.         rangeCheck(index);  
  33.         checkForComodification();  
  34.         E oldValue = ArrayList.this.elementData(offset + index);  
  35.         ArrayList.this.elementData[offset + index] = e;  
  36.         return oldValue;  
  37.     }  
  38.   
  39.     public E get(int index) {  
  40.         rangeCheck(index);  
  41.         checkForComodification();  
  42.         return ArrayList.this.elementData(offset + index);  
  43.     }  
  44.   
  45.     public int size() {  
  46.         checkForComodification();  
  47.         return this.size;  
  48.     }  
  49.   
  50.     public void add(int index, E e) {  
  51.         rangeCheckForAdd(index);  
  52.         checkForComodification();  
  53.         parent.add(parentOffset + index, e);  
  54.         this.modCount = parent.modCount;  
  55.         this.size++;  
  56.     }  
  57.   
  58.     public E remove(int index) {  
  59.         rangeCheck(index);  
  60.         checkForComodification();  
  61.         E result = parent.remove(parentOffset + index);  
  62.         this.modCount = parent.modCount;  
  63.         this.size--;  
  64.         return result;  
  65.     }  
  66.   
  67.     protected void removeRange(int fromIndex, int toIndex) {  
  68.         checkForComodification();  
  69.         parent.removeRange(parentOffset + fromIndex,  
  70.                            parentOffset + toIndex);  
  71.         this.modCount = parent.modCount;  
  72.         this.size -= toIndex - fromIndex;  
  73.     }  
  74.   
  75.     public boolean addAll(Collection<? extends E> c) {  
  76.         return addAll(this.size, c);  
  77.     }  
  78.   
  79.     public boolean addAll(int index, Collection<? extends E> c) {  
  80.         rangeCheckForAdd(index);  
  81.         int cSize = c.size();  
  82.         if (cSize==0)  
  83.             return false;  
  84.   
  85.         checkForComodification();  
  86.         parent.addAll(parentOffset + index, c);  
  87.         this.modCount = parent.modCount;  
  88.         this.size += cSize;  
  89.         return true;  
  90.     }  
  91.   
  92.     public Iterator<E> iterator() {  
  93.         return listIterator();  
  94.     }  
  95.   
  96.     public ListIterator<E> listIterator(final int index) {  
  97.         checkForComodification();  
  98.         rangeCheckForAdd(index);  
  99.         final int offset = this.offset;  
  100.   
  101.         return new ListIterator<E>() {  
  102.             int cursor = index;  
  103.             int lastRet = -1;  
  104.             int expectedModCount = ArrayList.this.modCount;  
  105.   
  106.             public boolean hasNext() {  
  107.                 return cursor != SubList.this.size;  
  108.             }  
  109.   
  110.             @SuppressWarnings("unchecked")  
  111.             public E next() {  
  112.                 checkForComodification();  
  113.                 int i = cursor;  
  114.                 if (i >= SubList.this.size)  
  115.                     throw new NoSuchElementException();  
  116.                 Object[] elementData = ArrayList.this.elementData;  
  117.                 if (offset + i >= elementData.length)  
  118.                     throw new ConcurrentModificationException();  
  119.                 cursor = i + 1;  
  120.                 return (E) elementData[offset + (lastRet = i)];  
  121.             }  
  122.   
  123.             public boolean hasPrevious() {  
  124.                 return cursor != 0;  
  125.             }  
  126.   
  127.             @SuppressWarnings("unchecked")  
  128.             public E previous() {  
  129.                 checkForComodification();  
  130.                 int i = cursor - 1;  
  131.                 if (i < 0)  
  132.                     throw new NoSuchElementException();  
  133.                 Object[] elementData = ArrayList.this.elementData;  
  134.                 if (offset + i >= elementData.length)  
  135.                     throw new ConcurrentModificationException();  
  136.                 cursor = i;  
  137.                 return (E) elementData[offset + (lastRet = i)];  
  138.             }  
  139.   
  140.             public int nextIndex() {  
  141.                 return cursor;  
  142.             }  
  143.   
  144.             public int previousIndex() {  
  145.                 return cursor - 1;  
  146.             }  
  147.   
  148.             public void remove() {  
  149.                 if (lastRet < 0)  
  150.                     throw new IllegalStateException();  
  151.                 checkForComodification();  
  152.   
  153.                 try {  
  154.                     SubList.this.remove(lastRet);  
  155.                     cursor = lastRet;  
  156.                     lastRet = -1;  
  157.                     expectedModCount = ArrayList.this.modCount;  
  158.                 } catch (IndexOutOfBoundsException ex) {  
  159.                     throw new ConcurrentModificationException();  
  160.                 }  
  161.             }  
  162.   
  163.             public void set(E e) {  
  164.                 if (lastRet < 0)  
  165.                     throw new IllegalStateException();  
  166.                 checkForComodification();  
  167.   
  168.                 try {  
  169.                     ArrayList.this.set(offset + lastRet, e);  
  170.                 } catch (IndexOutOfBoundsException ex) {  
  171.                     throw new ConcurrentModificationException();  
  172.                 }  
  173.             }  
  174.   
  175.             public void add(E e) {  
  176.                 checkForComodification();  
  177.   
  178.                 try {  
  179.                     int i = cursor;  
  180.                     SubList.this.add(i, e);  
  181.                     cursor = i + 1;  
  182.                     lastRet = -1;  
  183.                     expectedModCount = ArrayList.this.modCount;  
  184.                 } catch (IndexOutOfBoundsException ex) {  
  185.                     throw new ConcurrentModificationException();  
  186.                 }  
  187.             }  
  188.   
  189.             final void checkForComodification() {  
  190.                 if (expectedModCount != ArrayList.this.modCount)  
  191.                     throw new ConcurrentModificationException();  
  192.             }  
  193.         };  
  194.     }  
  195.   
  196.     public List<E> subList(int fromIndex, int toIndex) {  
  197.         subListRangeCheck(fromIndex, toIndex, size);  
  198.         return new SubList(this, offset, fromIndex, toIndex);  
  199.     }  
  200.   
  201.     private void rangeCheck(int index) {  
  202.         if (index < 0 || index >= this.size)  
  203.             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));  
  204.     }  
  205.   
  206.     private void rangeCheckForAdd(int index) {  
  207.         if (index < 0 || index > this.size)  
  208.             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));  
  209.     }  
  210.   
  211.     private String outOfBoundsMsg(int index) {  
  212.         return "Index: "+index+", Size: "+this.size;  
  213.     }  
  214.   
  215.     private void checkForComodification() {  
  216.         if (ArrayList.this.modCount != this.modCount)  
  217.             throw new ConcurrentModificationException();  
  218.     }  
  219. }  

ArrayList的subList方法,首先调用subListRangeCheck方法做了一个范围检查.
然后创建并返回了一个SubList的内部类对象.

仔细对比SubList和ArrayList的定义.
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

private class SubList extends AbstractList<E> implements RandomAccess

他们同样继承了AbstractList,并实现了RandomAccess标记接口.
而AbstractList是一个抽象类,除了一些抽象方法,还有一些方法干脆没有实现.
比如:
  1. abstract public E get(int index);  
  2. public E set(int index, E element) {  
  3.     throw new UnsupportedOperationException();  
  4. }  
  5.   
  6. public void add(int index, E element) {  
  7.     throw new UnsupportedOperationException();  
  8. }  
  9.   
  10. public E remove(int index) {  
  11.     throw new UnsupportedOperationException();  
  12. }  


在创建SubList内部类的时候,
new SubList(this, 0, fromIndex, toIndex);
实际上将外部的ArrayList对象,传入了内部类作为一个数据成员,即 AbstractList parent
并且记录了偏移量和Size等信息.

  1. private final AbstractList<E> parent;  
  2. private final int parentOffset;  
  3. private final int offset;  
  4. int size;  
  5.   
  6. SubList(AbstractList<E> parent,  
  7.         int offset, int fromIndex, int toIndex) {  
  8.     this.parent = parent;  
  9.     this.parentOffset = fromIndex;  
  10.     this.offset = offset + fromIndex;  
  11.     this.size = toIndex - fromIndex;  
  12.     this.modCount = ArrayList.this.modCount;  
  13. }  

SubList的方法调用,使用了两种方式
1.因为内部类可以访问外部类的方法和属性,所以一些操作直接使用外部类的方法
2.由于内部类 AbstractList parent指向外部类的对象,有一些操作调用parent的方法,通过多态性调用了外部类的方法.

代码风格似乎不太统一..

add和remove都是调用抽象类的方法,通过多态性调用了ArrayList的方法
  1. public void add(int index, E e) {  
  2.     rangeCheckForAdd(index);  
  3.     checkForComodification();  
  4.     parent.add(parentOffset + index, e);  
  5.     this.modCount = parent.modCount;  
  6.     this.size++;  
  7. }  
  8.   
  9. public E remove(int index) {  
  10.     rangeCheck(index);  
  11.     checkForComodification();  
  12.     E result = parent.remove(parentOffset + index);  
  13.     this.modCount = parent.modCount;  
  14.     this.size--;  
  15.     return result;  
  16. }  

而get和set方法,又是通过内部类可以直接访问外部类的特性.
  1. public E set(int index, E e) {  
  2.     rangeCheck(index);  
  3.     checkForComodification();  
  4.     E oldValue = ArrayList.this.elementData(offset + index);  
  5.     ArrayList.this.elementData[offset + index] = e;  
  6.     return oldValue;  
  7. }  
  8.   
  9. public E get(int index) {  
  10.     rangeCheck(index);  
  11.     checkForComodification();  
  12.     return ArrayList.this.elementData(offset + index);  
  13. }  

有点意思.

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/29254281/viewspace-2121834/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/29254281/viewspace-2121834/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值