概述

  ArrayList实质上就是可变数组的实现,着重理解:add、get、set、remove、iterator的实现,我们将关注一下问题。

  1、创建ArrayList的时候,默认给数组的长度设置为10。

  2、当set、remove、set的时候,如何解决越界问题?

  3、当add的时候,如何解决扩容问题?

  4、由于数组是不可变的时候,我们需要频繁重新新建数组重新赋值。

模拟实现

1、ArrayList定义变量与初始化。

  1. //定义存储数据的数组
  2. private transient Object [] elementData;
  3. //容量大小
  4. private int size;
  5. //默认构造器设置数组长度为10
  6. public MyArrayList() {
  7. this(10);
  8. }
  9. </span><span style="color: #0000ff;">public</span> MyArrayList(<span style="color: #0000ff;">int</span><span style="color: #000000;"> capacity)  {
  10.     </span><span style="color: #0000ff;">super</span><span style="color: #000000;">();
  11.     </span><span style="color: #0000ff;">if</span>(capacity&lt;0<span style="color: #000000;">){
  12.         </span><span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> IllegalArgumentException("数字不能小于0"<span style="color: #000000;">);
  13.     }
  14.     elementData</span>=<span style="color: #0000ff;">new</span><span style="color: #000000;"> Object[capacity];
  15. }</span></pre>
  16.  

2、解决越界问题:当索引值小于0或者索引值大于等于size就将越界。

  1. public void rangeCheck(int index){
  2. if(index<0 ||index>this.size){
  3. throw new IndexOutOfBoundsException("越界"+index);
  4. }
  5. }

3、解决扩容问题:普通扩容(new=old+old*2)、索引值依然大于普通扩容(new=index)、当超过int的取值范围(int的最大范围-8)

  1. public void ensureCapacity(int minCapacity){
  2. if(minCapacity>elementData.length){
  3. //获得初始容器大小
  4. int oldCapacity=elementData.length;
  5. //新的容器大小:初始容器大小+2初始容器大小(不懂为啥这样加)
  6. int newCapacity=oldCapacity+(oldCapacity>>1);
  7. //当新增以后,还不能满足索引长度,即将数组设置为最小索引长度
  8. if(newCapacity<minCapacity){
  9. newCapacity=minCapacity;
  10. }
  11. //当超过int的范围的时候
  12. if(minCapacity>Integer.MAX_VALUE-8){
  13. newCapacity=Integer.MAX_VALUE-8;
  14. }
  15. Object [] elments=new Object[newCapacity];
  16. //创建新的数组重新赋值。
  17. System.arraycopy(elementData,0,elments,0,size);
  18. elementData=elments;
  19. }
  20. }

4、谈谈迭代器:hasNext():判断是否有下一个、next():当前游标指向的值、remove():删除刚变过过的元素;

  1. private class Iter implements Iterator{
  2. //游标
  3. private int cursor=0;
  4. //指向刚遍历过的元素
  5. private int lastRet=0;
  6. public boolean hasNext() {
  7. return size!=cursor;
  8. }
  9.     </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Object next() {
  10.         </span><span style="color: #0000ff;">int</span> i =<span style="color: #000000;">cursor;
  11.         </span><span style="color: #0000ff;">if</span>(i&gt;=<span style="color: #000000;">size){
  12.             </span><span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span><span style="color: #000000;"> NoSuchElementException();
  13.         }
  14.         cursor</span>=i+1<span style="color: #000000;">;
  15.         </span><span style="color: #0000ff;">return</span> elementData[lastRet=<span style="color: #000000;">i];
  16.     }
  17.     </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> remove() {
  18.         </span><span style="color: #0000ff;">if</span>(cursor&lt;0<span style="color: #000000;">){
  19.             </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> IllegalThreadStateException();
  20.         }
  21.         MyArrayList.</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.remove(cursor);
  22.         cursor</span>=<span style="color: #000000;">lastRet;
  23.         </span><span style="color: #008000;">//</span><span style="color: #008000;">当删除一个元素的时候,赋值为0</span>
  24.         lastRet=-1<span style="color: #000000;">;
  25.     }
  26. }</span></pre>
  27.  

5、我相信乐忠于理解源码的同学的基础,弄清楚以上问题,应该ArrayList就没有问题了。

  1. public class MyArrayList<E> {
  2. //定义存储数据的数组
  3. private transient Object [] elementData;
  4. //容量大小
  5. private int size;
  6. //默认构造器设置数组长度为10
  7. public MyArrayList() {
  8. this(10);
  9. }
  10. </span><span style="color: #0000ff;">public</span> MyArrayList(<span style="color: #0000ff;">int</span><span style="color: #000000;"> capacity)  {
  11.     </span><span style="color: #0000ff;">super</span><span style="color: #000000;">();
  12.     </span><span style="color: #0000ff;">if</span>(capacity&lt;0<span style="color: #000000;">){
  13.         </span><span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> IllegalArgumentException("数字不能小于0"<span style="color: #000000;">);
  14.     }
  15.     elementData</span>=<span style="color: #0000ff;">new</span><span style="color: #000000;"> Object[capacity];
  16. }
  17. </span><span style="color: #0000ff;">public</span> E get(<span style="color: #0000ff;">int</span><span style="color: #000000;"> index) {
  18.     rangeCheck(index);
  19.     </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> (E) elementData[index];
  20. }
  21. </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> set(<span style="color: #0000ff;">int</span><span style="color: #000000;"> index, E element) {
  22.     rangeCheck(index);
  23.     ensureCapacity(index</span>+1<span style="color: #000000;">);
  24.     E oldVlue</span>=<span style="color: #000000;"> (E) elementData[index];
  25.     </span><span style="color: #0000ff;">this</span>.elementData[index]=<span style="color: #000000;">element;
  26. }
  27. </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> add(E e) {
  28.     ensureCapacity(size</span>+1<span style="color: #000000;">);
  29.     elementData[size]</span>=<span style="color: #000000;">e;
  30.     size</span>++<span style="color: #000000;">;
  31. }
  32. </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> add(<span style="color: #0000ff;">int</span><span style="color: #000000;"> index, E element) {
  33.     rangeCheck(index);
  34.     ensureCapacity(index</span>+1<span style="color: #000000;">);
  35.     </span><span style="color: #008000;">//</span><span style="color: #008000;">动态数组</span>
  36.     System.arraycopy(elementData,index,elementData,index+1,size-<span style="color: #000000;">index);
  37.     elementData[index]</span>=<span style="color: #000000;">element;
  38.     size</span>++<span style="color: #000000;">;
  39. }
  40. </span><span style="color: #008000;">//</span><span style="color: #008000;">移除</span>
  41. <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> remove(<span style="color: #0000ff;">int</span><span style="color: #000000;"> index) {
  42.     rangeCheck(index);
  43.     E oldVlue</span>=<span style="color: #000000;"> (E) elementData[index];
  44.     </span><span style="color: #0000ff;">int</span> moved=size-index-1<span style="color: #000000;">;
  45.     </span><span style="color: #0000ff;">if</span>(moved&gt;0<span style="color: #000000;">)
  46.         System.arraycopy(elementData,index</span>+1,elementData,index,size-<span style="color: #000000;">index);<br />    elementData[--size]=null;
  47. }
  48. </span><span style="color: #008000;">//</span><span style="color: #008000;">判断是否越界</span>
  49. <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> rangeCheck(<span style="color: #0000ff;">int</span><span style="color: #000000;"> index){
  50.     </span><span style="color: #0000ff;">if</span>(index&lt;0 ||index&gt;<span style="color: #0000ff;">this</span><span style="color: #000000;">.size){
  51.         </span><span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> IndexOutOfBoundsException("越界"+<span style="color: #000000;">index);
  52.     }
  53. }
  54. </span><span style="color: #008000;">//</span><span style="color: #008000;">扩容</span>
  55. <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> ensureCapacity(<span style="color: #0000ff;">int</span><span style="color: #000000;"> minCapacity){
  56.     </span><span style="color: #0000ff;">if</span>(minCapacity&gt;<span style="color: #000000;">elementData.length){
  57.         </span><span style="color: #008000;">//</span><span style="color: #008000;">获得初始容器大小</span>
  58.         <span style="color: #0000ff;">int</span> oldCapacity=<span style="color: #000000;">elementData.length;
  59.         </span><span style="color: #008000;">//</span><span style="color: #008000;">新的容器大小:初始容器大小+2初始容器大小(不懂为啥这样加)</span>
  60.         <span style="color: #0000ff;">int</span> newCapacity=oldCapacity+(oldCapacity&gt;&gt;1<span style="color: #000000;">);
  61.         </span><span style="color: #008000;">//</span><span style="color: #008000;">当新增以后,还不能满足索引长度,即将数组设置为最小索引长度</span>
  62.         <span style="color: #0000ff;">if</span>(newCapacity&lt;<span style="color: #000000;">minCapacity){
  63.             newCapacity</span>=<span style="color: #000000;">minCapacity;
  64.         }
  65.         </span><span style="color: #008000;">//</span><span style="color: #008000;">当超过int的范围的时候</span>
  66.         <span style="color: #0000ff;">if</span>(minCapacity&gt;Integer.MAX_VALUE-8<span style="color: #000000;">){
  67.             newCapacity</span>=Integer.MAX_VALUE-8<span style="color: #000000;">;
  68.         }
  69.         Object [] elments</span>=<span style="color: #0000ff;">new</span><span style="color: #000000;"> Object[newCapacity];
  70.         </span><span style="color: #008000;">//</span><span style="color: #008000;">创建新的数组重新赋值。</span>
  71.         System.arraycopy(elementData,0,elments,0<span style="color: #000000;">,size);
  72.         elementData</span>=<span style="color: #000000;">elments;
  73.     }
  74. }
  75. </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> size(){
  76.     </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> size;
  77. }
  78. </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Iterator iterator(){
  79.     </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">new</span><span style="color: #000000;"> Iter();
  80. }
  81. </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">class</span> Iter <span style="color: #0000ff;">implements</span><span style="color: #000000;"> Iterator{
  82.     </span><span style="color: #008000;">//</span><span style="color: #008000;">游标</span>
  83.     <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">int</span> cursor=0<span style="color: #000000;">;
  84.     </span><span style="color: #008000;">//</span><span style="color: #008000;">指向刚遍历过的元素</span>
  85.     <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">int</span> lastRet=0<span style="color: #000000;">;
  86.     </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> hasNext() {
  87.         </span><span style="color: #0000ff;">return</span> size!=<span style="color: #000000;">cursor;
  88.     }
  89.     </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Object next() {
  90.         </span><span style="color: #0000ff;">int</span> i =<span style="color: #000000;">cursor;
  91.         </span><span style="color: #0000ff;">if</span>(i&gt;=<span style="color: #000000;">size){
  92.             </span><span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span><span style="color: #000000;"> NoSuchElementException();
  93.         }
  94.         cursor</span>=i+1<span style="color: #000000;">;
  95.         </span><span style="color: #0000ff;">return</span> elementData[lastRet=<span style="color: #000000;">i];
  96.     }
  97.     </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> remove() {
  98.         </span><span style="color: #0000ff;">if</span>(cursor&lt;0<span style="color: #000000;">){
  99.             </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> IllegalThreadStateException();
  100.         }
  101.         MyArrayList.</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.remove(cursor);
  102.         cursor</span>=<span style="color: #000000;">lastRet;
  103.         </span><span style="color: #008000;">//</span><span style="color: #008000;">当删除一个元素的时候,赋值为0</span>
  104.         lastRet=-1<span style="color: #000000;">;
  105.     }
  106. }
  107. </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String [] args){
  108.     MyArrayList ls</span>=<span style="color: #0000ff;">new</span><span style="color: #000000;"> MyArrayList();
  109.     ls.add(</span>123<span style="color: #000000;">);
  110.     ls.add(</span>123<span style="color: #000000;">);
  111.     ls.set(</span>0,456<span style="color: #000000;">);
  112.     ls.remove(</span>1<span style="color: #000000;">);
  113.     System.out.println(ls.size());
  114.     System.out.println(ls.get(</span>0<span style="color: #000000;">));
  115.     Iterator it</span>=<span style="color: #000000;">ls.iterator();
  116.     </span><span style="color: #0000ff;">while</span><span style="color: #000000;">(it.hasNext()){
  117.         System.out.println(it.next());
  118.     }
  119. }
  120.  
  121. }

JAVA容器-模拟ArrayList的底层实现的更多相关文章

  1. JAVA容器-模拟LinkedList实现(双链表)

    概述 LinkedList实质上就是双向链表的拓展的实现,我们将关注一下问题.LinkedList 1.双向链表怎么来实现插入.删除.查询? 2.利用二分法提高查询效率. 3.不同步,线程不安全,需要 ...

  2. 【Java心得总结五】Java容器上——容器初探

    在数学中我们有集合的概念,所谓的一个集合,就是将数个对象归类而分成为一个或数个形态各异的大小整体. 一般来讲,集合是具有某种特性的事物的整体,或是一些确认对象的汇集.构成集合的事物或对象称作元素或是成 ...

  3. 迭代器模式在 Java 容器中的实现

    迭代器接口是迭代器模式实现的精髓: public interface Iterator<E> { boolean hasNext(); E next(); ... } 假设某容器名为 Xx ...

  4. 理解java容器底层原理--手动实现ArrayList

    为了照顾初学者,我分几分版本发出来 版本一:基础版本 实现对象创建.元素添加.重新toString() 方法 package com.xzlf.collection; /** * 自定义一个Array ...

  5. Java 容器源码分析之 ArrayList

    概览 ArrayList是最常使用的集合类之一了.在JDK文档中对ArrayList的描述是:ArrayList是对list接口的一种基于可变数组的实现.ArrayList类的声明如下: 12 pub ...

  6. Java容器学习之ArrayList

    一.概述 ArrayList是java中十分常用的集合类,继承于AbstractList,并实现了List.RandomAccess.Cloneable和Serializable接口.ArrayLis ...

  7. Java容器源码解析之——ArrayList

    public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess ...

  8. Java容器深入浅出之List、ListIterator和ArrayList

    List是Collection接口的子接口,表示的是一种有序的.可重复元素的集合. List接口的主要实现类ArrayList和Vector,底层都是维护了一套动态的,可扩展长度的Object[]数组 ...

  9. Java 的 ArrayList 的底层数据结构

    1. 数据结构--ArrayList源码摘要 ublic class ArrayList<E> extends AbstractList<E> implements List& ...

随机推荐

  1. Term Term ssh登陆linux后 显示乱码

    setup----terminal----locale----“chinese” OK!!!!!

  2. openjudge-NOI 2.6-2718 移动路线

    题目链接:http://noi.openjudge.cn/ch0206/2718/ 题解: 递推,某一个点只能从其左边或者下边走过来 f[i][j]存储(i,j)这个点上的结果,即f[i][j]=f[ ...

  3. Mac 终端自动补全忽略大小写

    打开终端,输入:nano .inputrc 在里面粘贴上以下语句: set completion-ignore-case onset show-all-if-ambiguous onTAB: menu ...

  4. C/C++——[02] 运算符和表达式

    C/C++中表示数据运算的符号称为“运算符”.运算符所用到的操作数个数,称为运算符的“目数”. C/C++语言的运算符有赋值运算符.算术运算符.逻辑运算符.位运算符等多类. 将变量.常量等用运算符连接 ...

  5. js获取系统时间

    //------------------------------------获取系统日期时间 var oDate=new Date(); //alert(oDate.getFullYear());// ...

  6. beego小技巧两则:通过命令行自定义端口和环境,url中带有中划线处理

    1,通过命令行自定义端口和环境 先用flag提取参数,如果要环境,就反向注进去, 如果是端口,就打到beego.Run函数里去. 2,在作router里的url解析时,如果URL中含有-中划线,用严格 ...

  7. Roman to Integer & Integer to Roman

    题目: Given a roman numeral, convert it to an integer. Input is guaranteed to be within the range from ...

  8. 在WebClient类中保持Session

    string url = context.Request["url"]; WebClient MyWebClient = new WebClient(); // 获取或设置用于向I ...

  9. Error: Exception was raised when calling event-notify Vuser function in extension parameng.dll: System Exceptions: EXCEPTION_ACCESS_VIOLATION

    解决方法:在C 盘新建一个TEMP目录,把环境变量TMP,TEMP的值设置成环境变量,重启计算机

  10. Java学习笔记之:Java Servlet 过滤器配置

    一.步骤 1.创建一类实现Filter接口,重写父类的方法 public class SimpleFilter implements Filter { public void destroy() { ...