阅读 99

ArrayList的手工简单实现

ArrayList的底层原理是用数组实现的,所以我们就可以自定义实现一个ArrayList,主要实现一些简单的方法,其实有的方法本质上也是数组的拷贝,目的是深入体会底层原理,加深对ArrayList容器的理解。

首先:我们需要一个自定义数组,元素大小,默认容量和有参无参构造方法,以便创建默认或者指定容量大小的容器。

    /**      * 自定义数组      */     private Object[] elementData;     /**      * 数组实际元素大小      */     private int size;     /**      * 默认容器的容量      */     private static final int DEFAULT_CAPACITY = 10;     public SXArrayList(){         elementData = new Object[DEFAULT_CAPACITY];     }     public SXArrayList(int capacity){         elementData = new Object[capacity];     } 复制代码

其次:添加add方法,给容器添加元素。添加元素之前要判断是否需要扩容,扩容的本质也是数组的复制,定义一个更大的数组,再把原来的数组复制过去。什么时候需要扩容呢?就是当容器满了的时候,我们就定义一个新的数组,容量就是旧数组容量+旧数组容量的一半(注意这里是数组容量大小,不是元素大小),这里我们用位运算,效率高,最后把新数组的引用赋给旧数组。

 public void add(Object obj){         //如果容量满了 就需要扩容了         if (size == elementData.length){             Object[] newArray = new Object[elementData.length + (elementData.length >> 1)];             System.arraycopy(elementData, 0, newArray, 0, size);             elementData = newArray;         }         elementData[size++] = obj;     } 复制代码

再次:添加remove移除方法,可以根据索引或者元素内容移除对应的元素。移除等操作前需要判断索引是否合法,移除的本质也是数组的复制,覆盖掉要移除的元素,假如移除的是最后一个元素就可以直接赋值为null就行。根据内容移除就是遍历容器找到内容相等的元素下标再执行remove操作。

 /**      * 移除容器中指定索引的元素内容      * @param index 索引      */     public void remove(int index){         indexCheck(index);         int numMoved = size - index - 1;         if (numMoved > 0)             System.arraycopy(elementData, index + 1, elementData, index, numMoved);         elementData[--size] = null;     }     /**      * 移除容器中指定的元素内容      * @param obj 元素内容      */     public void remove(Object obj){         if (null != obj){             for (int i = 0; i < size; i++) {                 if (obj.equals("" + elementData[i])){                     remove(i);                     break;                 }             }         }     }     private void indexCheck(int index){         if (index < 0 || index >= size){             throw new IndexOutOfBoundsException("索引不存在:" + index);         }     } 复制代码

再次:添加set方法,给容器中指定索引设置元素内容。这个也要判断索引是否合法,然后就直接给指定元素重新赋值。这里要重写toString方法,返回一个格式内容字符串,可以用于打印容器内容。

/**      * 给容器中指定索引设置元素内容      * @param index 索引      * @param obj 元素内容      */     public void set(int index, Object obj){         indexCheck(index);         elementData[index] = obj;     }     /**      * 重写toString方法      * @return 返回元素内容      */     @Override     public String toString() {         StringBuilder sb = new StringBuilder();         sb.append("[");         for (int i = 0; i < size; i++) {             sb.append(elementData[i]).append(",");         }         sb.setCharAt(sb.length()-1,']');         return sb.toString();     } 复制代码

最后:添加get,size等简单的方法,最后main方法简单测试一下,结果正常,后期还可以完善添加泛型,加深理解和记忆。

public static void main(String[] args) {         SXArrayList list = new SXArrayList();         for (int i = 0 ;i < 26;i++){             list.add((char)(i+97));         }         System.out.println(list);         list.remove(25);         System.out.println(list);         list.remove("d");         System.out.println(list);         System.out.println(list.get(2));         list.set(0,"aa");         System.out.println(list);     } 复制代码

[a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z] [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y] [a,b,c,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y] c [aa,b,c,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y] 复制代码

完整代码如下:

/**  * 手工实现ArrayList  */ public class SXArrayList {     /**      * 自定义数组      */     private Object[] elementData;     /**      * 数组实际元素大小      */     private int size;     /**      * 默认容器的容量      */     private static final int DEFAULT_CAPACITY = 10;     public SXArrayList(){         elementData = new Object[DEFAULT_CAPACITY];     }     public SXArrayList(int capacity){         elementData = new Object[capacity];     }     /**      * 获取容器元素大小      * @return 返回大小      */     public int size(){         return size;     }     /**      * 判断容器里是否有元素内容      * @return 返回是否      */     public boolean isEmpty(){         return size == 0;     }     /**      * 给容器添加元素      * @param obj 添加的元素内容      */     public void add(Object obj){         //如果容量满了 就需要扩容了         if (size == elementData.length){             Object[] newArray = new Object[elementData.length + (elementData.length >> 1)];             System.arraycopy(elementData, 0, newArray, 0, size);             elementData = newArray;         }         elementData[size++] = obj;     }     /**      * 获取容器中指定索引的元素内容      * @param index 索引      * @return 返回元素内容      */     public Object get(int index){         indexCheck(index);         return elementData[index];     }     /**      * 移除容器中指定索引的元素内容      * @param index 索引      */     public void remove(int index){         indexCheck(index);         int numMoved = size - index - 1;         if (numMoved > 0)             System.arraycopy(elementData, index + 1, elementData, index, numMoved);         elementData[--size] = null;     }     /**      * 移除容器中指定的元素内容      * @param obj 元素内容      */     public void remove(Object obj){         if (null != obj){             for (int i = 0; i < size; i++) {                 if (obj.equals("" + elementData[i])){                     remove(i);                     break;                 }             }         }     }     /**      * 给容器中指定索引设置元素内容      * @param index 索引      * @param obj 元素内容      */     public void set(int index, Object obj){         indexCheck(index);         elementData[index] = obj;     }     /**      * 重写toString方法      * @return 返回元素内容      */     @Override     public String toString() {         StringBuilder sb = new StringBuilder();         sb.append("[");         for (int i = 0; i < size; i++) {             sb.append(elementData[i]).append(",");         }         sb.setCharAt(sb.length()-1,']');         return sb.toString();     }     /**      * 检查索引是否越界      * @param index 索引      */     private void indexCheck(int index){         if (index < 0 || index >= size){             throw new IndexOutOfBoundsException("索引不存在:" + index);         }     } }


作者:法外狂徒张三三
链接:https://juejin.cn/post/7021535770066288654


文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐