ArrayList源码的解释和用代码简单实现

一.为什么要用ArrayList?

数组是一个重要的数据数据结构,但它有一个明显的缺点,长度一旦设定将不可以改变。ArrayList的底层也是用数组实现,所以它拥有数组的优点,方便查询等,但ArrayList的数组长度可以改变,也被称为动态数组。

二.ArrayList的源码解析

2.1属性和构造方法

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

ArrayList是AbstractList的子类,AbstractList是一个抽象类。ArraList的接口有List,RandomAccess,Serializable.

 @java.io.Serial
    private static final long serialVersionUID = 8683452581122892189L;

版本信息

private static final int DEFAULT_CAPACITY = 10;

初始容量

private static final Object[] EMPTY_ELEMENTDATA = {};

空的数组

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
缺省空对象数组
  transient Object[] elementData;

元素数组

private int size;

实际数据元素的个数

public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

有参构造方法,有于自定义数组容量大小。大于0,将初始容量大小设为 initialCapacity。

等于0,就为空数组。小于0,抛出异常。

public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

无参构造方法,元素数组等于空的对象数组。

2.2核心方法

 private void add(E e, Object[] elementData, int s) {
        if (s == elementData.length)
            elementData = grow();
        elementData[s] = e;
        size = s + 1;
    }


如果传入的参数s等于元素数组的长度,就进行扩容,并把e元素传入元素数组下标为s的位置。下面我们看ArrayList的核心中的核心,扩容机制grow方法。

  private Object[] grow(int minCapacity) {
        int oldCapacity = elementData.length;
        if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            int newCapacity = ArraysSupport.newLength(oldCapacity,
                    minCapacity - oldCapacity, /* minimum growth */
                    oldCapacity >> 1           /* preferred growth */);
            return elementData = Arrays.copyOf(elementData, newCapacity);
        } else {
            return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
        }
    }

 传入一个最小容量。把元素数组的长度给oldCapacity(老容量),如果老容量大于0或者元素数组不等于缺省空对象数组,则第一个newCapacity(新容量),变为原来长度的1.5倍,把元素数组的容量改为新容量并返回,否则把10和最小容量比较,大的容量给元素数组。

public boolean add(E e) {
        modCount++;
        add(e, elementData, size);
        return true;
    }

在元素数组的末尾添元素。

public void add(int index, E element) {
        rangeCheckForAdd(index);
        modCount++;
        final int s;
        Object[] elementData;
        if ((s = size) == (elementData = this.elementData).length)
            elementData = grow();
        System.arraycopy(elementData, index,
                         elementData, index + 1,
                         s - index);
        elementData[index] = element;
        size = s + 1;
    }

在指定索引位置添加元素。先判断index的是否是正确的不正确抛出异常。定义一个整形s和一个元素数组。把size赋值给s,s如果等于元素数组长度,进行扩容。并把插入后面的元素下标加一。

 public E remove(int index) {
        Objects.checkIndex(index, size);
        final Object[] es = elementData;

        @SuppressWarnings("unchecked") E oldValue = (E) es[index];
        fastRemove(es, index);

        return oldValue;
    }

 指定位置删除,删除是每次进行数组复制,然后让旧的elementData置为null进行垃圾回收。

三.ArrayList的简单实在。

package Underlyingcode;

import java.io.PrintStream;
import java.util.Arrays;

public class MyArrayList {
		
	  private static final int d=10;
	  private static final Object [] a= {};//空元素数据 EMPTY_ELEMENTDATA
	  private static final Object [] b= {};//违约元素数据 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
	  private static Object [] c= {};//元素数据  elementData
	  private int size=0;
	 
	  
	  public MyArrayList() {
		  this.c=new Object[d];
	  }
	  //initialCapacity 初始容量
	  public MyArrayList(int size) throws Exception{
		   if(size > 0)
	            this.c = new Object[size];
		   else
			   throw new Exception("长度不允许小于零!");
	  }
	//增加元素
	  public void add(Object number) {
		 if(size>=c.length) {
			 Object [] zj =new Object[c.length];
			 for(int i=0;i<c.length;i++) {
				 zj[i]=c[i];
			 }
			 int length=c.length+c.length/2;
			 c=new Object[length];
			 for(int j=0;j<zj.length;j++) {
				 c[j]=zj[j];
			 }
			zj = null;
		 }
		 c[size]=number;
		 size++;
	  }
	  //获取值
	  public Object get(int index) {
		  if(index<0||index>size) {
			  throw new ArrayIndexOutOfBoundsException("你乱输入索引");
		  }
		  return c[index];
	  } 
	// 搜索给定参数第一次出现的位置,使用 equals 方法进行相等性测试。
	  public int indexof(Object a) {
		  	int i;
		  for(i=0;i<c.length;i++) {
			  if(a.equals(c[i])) {
				  return i;
			  }
		  }
		  if(i==c.length) {
			  return -1;
		  }
		return 0;
	  }
	  // 移除此列表中指定位置上的元素.向左移动所有后续元素(将其索引减 1)。 
	  public void remove(int indenx) {
		  if(c[indenx]==null) {
			 System.out.println("这个索引对应的数据没有值");
		  }else {
			  for(int i=indenx;i<size;i++) {
				  c[i]=c[i+1];
			  }
		  }
	  }
	  //测试此列表中是否没有元素。
	  public boolean isEmpty() {
		  if(size==0) {
			  return false;
		  }else {
			  return true;
		  }
	  }
	  public static void main(String[]args) { 
		MyArrayList a=new MyArrayList();
		a.add(1);
		a.add(2);
		a.add(3);
		a.add(null);
		a.add(3);
		a.add(3);
		a.add(3);
		a.add(3);
		a.add(3);
		a.add(3);
		a.add(10);
		System.out.println(a.isEmpty());
		System.out.println(Arrays.toString(c));
		System.out.println(a.indexof(3));
		System.out.println(a.get(4));
		a.remove(4);
		System.out.println(Arrays.toString(c));
 }
}

运行结构

总结

ArrayList建立的空间是连续的,方便查询,但不方便删除和添加。注意ArrayLIst是不同步的,所以是不安全的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值