手写ArrayList

Posted 谢哥在彼方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手写ArrayList相关的知识,希望对你有一定的参考价值。

  ArrayList是Java中最为简单也是最为常用的容器之一,那么它的内部构造是什么呢?其实ArrayList的底层实现就是数组,它的各种方法就是对数组进行的一系列操作,例如对数组元素的修改,删除,位移,对数组长度的获取等。我们可以手写一个ArrayList容器,以助我们更好的理解这个容器:

  1 package ArraryList;
  2 
  3 import java.util.Arrays;
  4 import java.util.Iterator;
  5 
  6 /**
  7  * 深入迭代器的原理-->一个容器可以创建多个迭代器对象
  8  * 1.使用了内部类,实现迭代器
  9  * 2.使用Iterable实现foreach迭代
 10  * @author XieHuazhen
 11  *
 12  */
 13 public class MyArrayList<E> implements Iterable<E>{  //迭代器接口
 14     
 15     //数组存储值
 16     private Object[] elementData;
 17     //大小
 18     private int size;
 19     
 20     public MyArrayList(int initialCapacity) {
 21         if(initialCapacity>=0) {
 22             elementData = new Object[initialCapacity];
 23         }else {
 24             try {
 25                 throw new MyException();
 26             }catch(MyException e) {
 27                 e.printInit();
 28             }
 29         }
 30     }
 31     
 32     public MyArrayList() {
 33         this(0);
 34     }
 35     
 36     @SuppressWarnings("unchecked")
 37     private E elementData(int index) {
 38         return (E)elementData[index];
 39     }
 40     
 41     private void ensureCapacity() {
 42         if(size>=elementData.length) {
 43             elementData = Arrays.copyOf(elementData,size*2+1);
 44         }
 45     }
 46     
 47     private void rangeCheck(int index) {
 48         if(index<0||index>=size) {
 49             try {
 50                 throw new MyException();
 51             } catch (MyException e) {
 52                 e.printIndex();
 53             }
 54         }
 55     }
 56     
 57     public int size() {
 58         return size;
 59     }
 60     
 61     public boolean isEmpty() {
 62         return size==0;
 63     }
 64     
 65     public boolean contains(Object o) {
 66         return indexOf(o)>=0;
 67     }
 68     
 69     public int indexOf(Object o) {
 70         for(int i=0;i<size;++i) {
 71             if(elementData[i].equals(o))
 72                 return i;
 73         }
 74         return -1;
 75     }
 76     
 77     public E get(int index) {
 78         rangeCheck(index);
 79         return elementData(index);
 80     }
 81 
 82     public E set(int index,E element) {
 83         rangeCheck(index);
 84         E oldValue = elementData(index);
 85         elementData[index] = element;
 86         return oldValue;
 87     }
 88     
 89     public void add(E element) {
 90         ensureCapacity();
 91         elementData[size++] = element;
 92     }
 93     
 94     public void add(int index,E element) {
 95         rangeCheck(index);
 96         ensureCapacity();
 97         System.arraycopy(elementData,index,elementData,index+1,size-index);
 98         elementData[index] = element;
 99         ++size;
100     }
101     
102     public E remove(int index) {
103         rangeCheck(index);
104         E oldValue = elementData(index);
105         System.arraycopy(elementData,index+1,elementData,index,size-index-1);
106         elementData[--size] = null;
107         return oldValue;
108     }
109     
110     public boolean remove(E element) {
111         for(int i=0;i<size;++i) {
112             if(elementData[i].equals(element)) {
113                 remove(i);
114                 return true;
115             }
116         }
117         return false;
118     }
119     
120     //实现Iterable<E>接口的方法
121     @Override
122     public Iterator<E> iterator() {
123         return new MyIter();
124     }
125     
126     //内部类
127     private class MyIter implements Iterator<E>{
128         //计数器-->指针 游标
129         private int cursor;
130         private int lastRet = -1;
131         
132         //判断是否存在下一个
133         @Override
134         public boolean hasNext() {
135             return cursor!=size;
136         }
137         
138         //返回游标当前位置,并把游标移到下一位置
139         @SuppressWarnings("unchecked")
140         @Override
141         public E next() {
142             if(!hasNext()) {
143                 try {
144                     throw new MyException();
145                 } catch (MyException e) {
146                     e.printnext();
147                 }
148             }
149             lastRet = cursor;
150             return (E)elementData[cursor++];
151         }    
152         
153         //删除游标左面元素,执行完next后只能执行一次
154         @Override
155         public void remove() {
156             if(lastRet<0) {
157                 try {
158                     throw new MyException();
159                 } catch (MyException e) {
160                     e.printremove();
161                 }
162             }
163             System.arraycopy(elementData,lastRet+1,elementData,lastRet,size-lastRet-1);
164             cursor = lastRet;
165             lastRet = -1;
166             elementData[--size] = null;
167         }    
168     }
169     
170     public static void main(String[] args) {
171         MyArrayList<String> list = new MyArrayList<String>();
172         list.add("aaa");
173         list.add("bbb");
174         list.add("ccc");
175         list.add(2,"123");
176         list.remove("ccc");
177         //使用迭代器遍历
178         for(Iterator<String> itr=list.iterator();itr.hasNext();) {
179             System.out.println(itr.next());
180             //itr.remove();
181         }
182         
183         System.out.println("---------------------");
184         
185         //使用增强for循环遍历
186         for(String str:list){
187             System.out.println(str);
188         }
189     }
190 }
 1 package ArraryList;
 2 
 3 public class MyException extends Exception{
 4     
 5     private static final long serialVersionUID = 1L;
 6 
 7     public MyException() {
 8         System.out.print("出现异常:");
 9     }
10     
11     public void printIndex() {
12         System.out.println("索引范围越界!");
13         System.exit(1);
14     }
15     
16     public void printInit(){
17         System.out.println("请重新初始化");
18     }
19     
20     public void printnext() {
21         System.out.println("游标越界!");
22         System.exit(1);
23     }
24     
25     public void printremove() {
26         System.out.println("remove()只有在执行完next()后才能且只能执行一次!");
27         System.exit(1);
28     }
29 }

 

以上是关于手写ArrayList的主要内容,如果未能解决你的问题,请参考以下文章

手写数字识别——基于全连接层和MNIST数据集

前端面试题之手写promise

从0开始手写ArrayList动态数组

手写ArrayList

手写ArrayList

从0开始手写ArrayList动态数组和LinkedList双向链表