4.22Java自定义ArrayList底层+remove方法

4.22Java自定义ArrayList底层+remove方法

特点:

在ArrayList源码当中remove的特点是:

  1. 给一个索引,移除该索引下的索引值

  2. 给一个对象,然后进行逐个的比较(底层是通过equals方法比较),然后remove

代码实现:

package com.MyCollection;

/**
* 增加Remove方法
* @author Lucifer
*/
public class LcfArrayList05<E> {

   /*ArrayList底层有一个元素数组,用它来存储内容*/
   private Object[] elementData; //用来存储我们的内容的

   /*数组里面有多少元素---相当于计数器*/
   private int size;

   /*定义一个常量作为数组长度的默认长度*/
   private static final int DEFAULT_CAPACITY = 10;

   /*定义一个构造器,创建数组的时候给它默认长度*/
   public LcfArrayList05(){
       /*为数组新建对象*/
       elementData = new Object[DEFAULT_CAPACITY]; //将新建的Object对象赋值给Object数组名
  }

   /*第二个构造器像之前一样---传数字,封装方法*/
   public LcfArrayList05(int capacity){
       /*检查一下不能传负数*/
       if (capacity < 0){
           /*抛出异常*/
           throw new RuntimeException("容器容量不能为0");
      }else if (capacity == 0){
           /*默认创建一个容量为10的数组*/
           elementData = new Object[DEFAULT_CAPACITY]; //将新建的Object对象赋值给Object数组名
      }else {
           /*数组长度=传入的数值---定义了自己的一个小内容*/
           elementData = new Object[capacity];
      }
  }

   /*增加size方法*/
   public int size(){
       return size;
  }

   /*增加判断是否为空的方法*/
   //如果size=0返回true,非则返回false
   public boolean isEmpty(){
       return size == 0 ? true : false; //三元运算符
  }

   /*给add方法添加扩容操作*/
   public void add(E element){
       /*当siz长度==elementData的时候就需要扩容了---判断*/
       if (size == elementData.length){
           /*扩容的方法---定义一个更大的数组*/
           //采用源码当中的扩容方法
           Object[] newArray = new Object[elementData.length + (elementData.length >> 1)]; //这里计算的时候会有优先级问题,先算移位算法。如果不括起来JVM会先算前面的加法
           //将原来的数组的值拷贝给新的扩容的数组
           System.arraycopy(elementData,0,newArray,0,elementData.length);
           /*再将老数组对象内容赋值给原来的数组元素代替值,让JVM回收掉老数组对象内容---重新指向新的数组对象*/
           elementData = newArray;
      }
       elementData[size++] = element; //传入的值赋给新元素索引自增
  }

   /*增加一个get方法---访问修饰符、返回值、方法名、形参*/
   /*
   1.先写出方法---定义返回值、形参、方法名、修饰符等
   2.判断索引是否合法
    */
   public E get(int index){

       /*运行时先判断*/
       checkRange(index);

       return (E)elementData[index]; //转型+索引下标
  }

   /*增加一个set方法---访问修饰符、返回值(有、无)、方法名、形参*/
   public void set(E element, int index){

       checkRange(index);

       /*往里设置一个内容---核心代码*/
       elementData[index] = element; //传入的形参赋值给带索引的数组的索引、下标自增
  }

   /*因为get和set方法都需要判断,所以把合法判断变成方法封装起来,再get和set方法调用之前先运行该方法进行判断*/
   public void checkRange(int index){
       /*索引合法判断,找到索引的合法区间:[0,size)左闭右开*/
       if (index < 0 || index > size - 1){
           //不合法---处理办法:手动抛出一个异常,抛出异常要进行处理
           throw new RuntimeException("索引不合法" + index);
      }
  }

   /*增加Remove移除方法---传入对象*/
   public void remove(E element){
       /*将传进来的对象进行比较---和所有元素依次进行比较,获得第一个比较为true的,返回*/
       //遍历比较---for循环
       for (int i = 0; i < size; i++){
           //调用equals方法比较,和我们前面定义的get方法的索引下标的值
           if (element.equals(get(i))){
               //将该元素从此处移除---容器中所有的比较方法操作都是用的是equals而不是"=="
               remove(i); //从0开始比较,所以是i自增开始比较
          }
      }
  }

   /*增加移除指定位置的Remove方法*/
   public void remove(int index){
       /*假设当中有:a,b,c,d,e,f,g---要删除d就会变成a,b,c,e,f,g,h长度是8位,删除3号位置---原理同样是拷贝*/
       //Remove源码的底层实现也是通过拷贝实现
       //不可为0或者负数---分情况:>0,=0,<0
       int numMoved = elementData.length - index - 1;
       if (numMoved > 0){
           System.arraycopy(elementData,index + 1,elementData,index,numMoved);
      }
       //注意移动的时候是复制过去的,最后一位还有h
       elementData[--size] = null; //讲size - 1和size--合并 = --size
  }

   /*希望输出的结果可视化,重写toString方法*/
   @Override
   public String toString(){
       // TODO Auto-generated method stub
       StringBuilder sb = new StringBuilder();

       //打印出类似[a,b,c]的形式
       sb.append("[");
       for (int i = 0; i < size; i++){
           sb.append(elementData[i] + ",");
      }
       sb.setCharAt(sb.length()-1,']');

       return sb.toString();
  }

   /*在main方法当中做测试*/
   public static void main(String[] args) {
       /*调用方法创建对象*/
       LcfArrayList05 s1 = new LcfArrayList05();

       for (int i = 0; i < 40; i++){
           s1.add("Harden" + i);
      }
       s1.set("Lucifer",10);

       System.out.println(s1); //如果没有重写toString方法的话打印出的是类名+地址的hash值

       System.out.println(s1.get(39));

       s1.remove(10);
       s1.remove("Harden11");
       System.out.println(s1);

       System.out.println(s1.size);
       System.out.println(s1.isEmpty());
  }
}

 

It's a lonely road!!!
原文地址:https://www.cnblogs.com/JunkingBoy/p/14691065.html