ArrayList底层源码学习

本文详细解析了数组的基本操作,包括add、get、set、remove和indexOf等方法的实现原理。重点介绍了数组扩容机制,当元素数量达到数组容量时,如何通过创建新数组并复制元素来实现扩容。同时,阐述了各种操作的具体步骤,如添加元素时的index位置选择,获取、设置和删除元素的方法,以及查找元素位置的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

主要为add, get, set, remove, indexOf,数组扩容等内容的学习。

扩容:
扩容前提:size==elementData.length,也就是元素个数达到了数组容器的长度。
创建新的更大空间的(如size*2+1)数组对象,

Object[] newArray = new Object[size*2+1]

遍历原来数组元素,复制到新数组中,在将这个新数组重新赋值给同名字的elementData。

public Object[] grow() {
		if (size == elementData.length) {
			Object[] newArray = new Object[size*2+1];
			for (int i=0; i<elementData.length; i++) {
				newArray[i] = elementData[i];
			}
			elementData = newArray;
		}
		return elementData;
	}

数组添加元素:

elementData[s] = element;
size++;

记得不要忘了添加size++, 添加元素,size相应增大。
相反,remove元素后,不要忘了"- - size"。

1、add
类内部调用的add方法:先扩容,然后在index=size位置处,添加元素,size++

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

add (element):直接调用上方的内部类的私有方法add

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

add (index, element):先扩容,然后将index位置到最后的元素,全部往后挪一个位置,也就是复制到index+1,在将目标元素放入到数组index位置处,size++。

	public boolean add(int index, E element) {
		indexCheck(index);
		// 扩容
		elementData = grow();
		System.arraycopy(elementData, index, elementData, index+1, size-index);
		elementData[index] = element;
		size++;
		return true;
	}

2、get
get实际上就是用index从数组中取值

	public Object get(int index) {
		indexCheck(index);
		return elementData[index];
	}

3、remove
原理就是将index+1到最后的元素,往前挪一个位置,最后一个元素设为null,size-1。

	public E remove(int index) {
		indexCheck(index);
		E oldValue = (E) elementData[index];
		System.arraycopy(elementData, index+1, elementData, index, size-index-1);
		elementData[--size] = null;
		return oldValue;
	}

4、set
这个简单,直接将数组index位置处,赋值为目标元素。

	public boolean set(int index, E e) {
		elementData[index] = e;
		return true;
	}

5、indexOf
其实遍历数组,用equals来判断是否存在目标元素,有就返回对应 i,没有就返回-1.

public int indexOf(Object obj) {
		return indexOfRange(obj, 0, size);
	}
	
	
public int indexOfRange(Object obj, int start, int end) {
		if (obj == null) {
			for (int i=start; i<end; i++) {
				if (elementData[i] == null) {
					return i;
				}
			}
		} else {
			for (int i=start; i<=end; i++) {
				if (obj.equals(elementData[i])) {
					return i;
				}
			}
			
		}
		return -1;
	}

整体代码

package cn.sxt.oop.datastructure;

/**
 * practice of add()
 * add(index, element)或者add(element)两种添加元素方法,都需要考虑:扩容的问题,第二,要记得加size++,不然元素会变少
 * @author t_chenli
 * @param <E>
 *
 */
public class ArrayListAddPra<E> {

	Object[] elementData;
	private int size;
	private final Object[] EMPTY_ELEMENTDATA = {};
	
	public ArrayListAddPra() {
		this.elementData = EMPTY_ELEMENTDATA;
	}
	
	public ArrayListAddPra(int initialCapacity) {
		if (initialCapacity > 0) {
			elementData = new Object[initialCapacity];
		} else if (initialCapacity == 0) {
			elementData = EMPTY_ELEMENTDATA;
		} else {
			try {
				throw new Exception();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}	
	}
	
	public int size() {
		return size;
	}
	
	private void add(E e, Object[] obj, int s) {
		elementData = grow();
		elementData[s] = e;
		size++;
	}
	
	public boolean add(E e) {
		add(e, elementData, size);
		return true;
	}
	
	public Object[] grow() {
		if (size == elementData.length) {
			Object[] newArray = new Object[size*2+1];
			for (int i=0; i<elementData.length; i++) {
				newArray[i] = elementData[i];
			}
			elementData = newArray;
		}
		return elementData;
	}
	
	public boolean add(int index, E element) {
		indexCheck(index);
		//o 扩容
		elementData = grow();
		System.arraycopy(elementData, index, elementData, index+1, size-index);
		elementData[index] = element;
		size++;
		return true;
	}
	
	public Object get(int index) {
		indexCheck(index);
		return elementData[index];
	}
	
	public boolean set(int index, E e) {
		elementData[index] = e;
		return true;
	}
	
	public E remove(int index) {
		indexCheck(index);
		E oldValue = (E) elementData[index];
		System.arraycopy(elementData, index+1, elementData, index, size-index-1);
		elementData[--size] = null;
		return oldValue;
	}
	
	public int indexOf(Object obj) {
		return indexOfRange(obj, 0, size);
		
	}
	
	
	public int indexOfRange(Object obj, int start, int end) {
		if (obj == null) {
			for (int i=start; i<end; i++) {
				if (elementData[i] == null) {
					return i;
				}
			}
		} else {
			for (int i=start; i<=end; i++) {
				if (obj.equals(elementData[i])) {
					return i;
				}
			}
			
		}
		return -1;
	}
	
	private void ensureCapacity() {
		if (size == elementData.length) {
			
			try {
				throw new Exception();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	private void indexCheck(int index) {
		if (index<0 || index>=size) {
			try {
				throw new Exception();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		ArrayListAddPra list = new ArrayListAddPra();
		list.add("aaa");
		list.add("bbb");
		list.add(123);
		list.add(new Pandas());
		list.add(new String("one string"));
		
		System.out.println("######### add(element) test #############");
		for (int i=0; i<list.size(); i++) {
			System.out.println(list.get(i));
		}
		System.out.println("size: "+list.size());
		System.out.println("######### add(index,element) test #############");
		list.add(1, "Libao");
		for (int i=0; i<list.size(); i++) {
			System.out.println(list.get(i));
		}
		System.out.println("size: "+list.size());
		System.out.println("######### set(index, element) test  #############");
		list.set(1, "111");
		for (int i=0; i<list.size(); i++) {
			System.out.println(list.get(i));
		}
		System.out.println("size: "+list.size());
		System.out.println("#########  remove(index) test ###########");
		list.remove(0);
		for (int i=0; i<list.size(); i++) {
			System.out.println(list.get(i));
		}
		System.out.println("size: "+list.size());
		
		System.out.println("######### indexOf(obj) test  ############");
		System.out.println("index of 123: " + list.indexOf(123));
		System.out.println("index of bbb: " + list.indexOf("bbb"));
		
		System.out.println("######### 扩容 test #############");
		for (int i=1; i<11; i++) {
			list.add(i);
		}
		for (int i=0; i<list.size(); i++) {
			System.out.println(list.get(i));
		}
		System.out.println("size: "+list.size());
	}
}

class Pandas {
	
}

结果:

######### add(element) test #############
aaa
bbb
123
cn.sxt.oop.datastructure.Pandas@368239c8
one string
size: 5
######### add(index,element) test #############
aaa
Libao
bbb
123
cn.sxt.oop.datastructure.Pandas@368239c8
one string
size: 6
######### set(index, element) test #############
aaa
111
bbb
123
cn.sxt.oop.datastructure.Pandas@368239c8
one string
size: 6
######### remove(index) test ###########
111
bbb
123
cn.sxt.oop.datastructure.Pandas@368239c8
one string
size: 5
######### indexOf(obj) test ############
index of 123: 2
index of bbb: 1
######### 扩容 test #############
111
bbb
123
cn.sxt.oop.datastructure.Pandas@368239c8
one string
1
2
3
4
5
6
7
8
9
10
size: 15

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值