纯手写Arraylist集合框架

本文详细介绍了ArrayList集合框架,讲解了ArrayList基于数组的实现方式,初始容量为10,当添加元素导致容量不足时,会进行扩容,通常翻倍。文章还涉及List接口及其在Java集合框架中的地位,以及ArrayList的核心操作如添加和获取元素的方法实现。

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

纯手写Arraylist集合框架 相关视频教程 http://www.itmayiedu.com/front/couinfo/125/0

作者:蚂蚁课堂创始人-余胜军  


集合框架介绍

说明:对于以上的框架图有如下几点说明 

1.所有集合类都位于java.util包下。Java的集合类主要由两个接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口,这两个接口又包含了一些子接口或实现类。

2. 集合接口:6个接口(短虚线表示),表示不同集合类型,是集合框架的基础。

3. 抽象类:5个抽象类(长虚线表示),对集合接口的部分实现。可扩展为自定义集合类。

4. 实现类:8个实现类(实线表示),对接口的具体实现。

5.Collection 接口是一组允许重复的对象。

6.Set 接口继承Collection,集合元素不重复。

7.List 接口继承Collection,允许重复,维护元素插入顺序。

8.Map接口是键-值对象,与Collection接口没有什么关系。

9.Set、List和Map可以看做集合的三大类:

List集合是有序集合,集合中的元素可以重复,访问集合中的元素可以根据元素的索引来访问。

Set集合是无序集合,集合中的元素不可以重复,访问集合中的元素只能根据元素本身来访问(也是集合里元素不允许重复的原因)。

Map集合中保存Key-value对形式的元素,访问时只能根据每项元素的key来访问其value。

 

List框架接口

List集合代表一个有序集合,集合中每个元素都有其对应的顺序索引。List集合允许使用重复元素,可以通过索引来访问指定位置的集合元素。

 List接口继承于Collection接口,它可以定义一个允许重复的有序集合。因为List中的元素是有序的,所以我们可以通过使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。

 List接口为Collection直接接口。List所代表的是有序的Collection,即它用某种特定的插入顺序来维护元素顺序。用户可以对列表中每个元素的插入位置进行精确地控制,同时可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。实现List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。


ArrayList核心代码


 Arraylist底层基于数组实现


private Object[] elementData;

Arraylist底层默认数组初始化大小为10个object数组

public ExtArraylist() throws Exception {

      this(10);

}

     public ExtArraylist(intinitialCapacity) throws Exception {

      if (initialCapacity < 0){

            thrownewIllegalArgumentException("初始容量不能小于0 " + initialCapacity);

      }

      elementData = new Object[initialCapacity];

      }


添加元素后大于当前数组的长度,则进行扩容,将数组的长度增加原来数组的一半。

// 增大数组空间

      privatevoid grow(intminCapacity) {

      // overflow-conscious code

intoldCapacity = elementData.length;

      intnewCapacity = oldCapacity + (oldCapacity >>1); // 在原来容量的基础上加上

                                                                          // oldCapacity/2

if (newCapacity - minCapacity < 0)

      newCapacity = minCapacity; // 最少保证容量和minCapacity一样

      if (newCapacity - MAX_ARRAY_SIZE > 0)

           newCapacity = hugeCapacity(minCapacity); // 最多不能超过最大容量

      // minCapacity is usually close to size, so this is a win:

elementData = Arrays.copyOf(elementData, newCapacity);

      }

纯手写Arraylist集合代码


/**
 * 自定义 ArrayList集合<br>
 * 作者: 每特教育-余胜军<br>
 * 联系方式:QQ644064779|WWW.itmayiedu.com<br>
 */
public class ExtArrayList<E> implements ExtList<E> {
	// ArrayList底层采用数组存放
	private Object[] elementData;
	// 默认数组容量
	private static final int DEFAULT_CAPACITY = 10;
	// 记录实际ArrayList大小
	private int size;

	// ArrayList 指定 数组初始的容量
	public ExtArrayList(int initialCapacity) {
		if (initialCapacity < 0) {
			throw new IllegalArgumentException("初始容量不能小于0");
		}
		elementData = new Object[initialCapacity];
	}

	// 默认初始化容量为10;
	public ExtArrayList() {
		this(DEFAULT_CAPACITY);
	}

	// 线程安全问题ArrayList底层每次扩容是以1.5倍
	public void add(E e) {
		// 1.判断实际存放的数据容量是否大于elementData容量
		ensureExplicitCapacity(size + 1);
		// 2.使用下标进行赋值
		elementData[size++] = e;
	}

	public void add(int index, Object object) {
		// 1.判断实际存放的数据容量是否大于elementData容量
		ensureExplicitCapacity(size + 1);
		System.arraycopy(elementData, index, elementData, index + 1, size - index);
		elementData[index] = object;
		size++;
	}

	// int minCapacity 最当前size+1
	private void ensureExplicitCapacity(int minCapacity) {
		if (size == elementData.length) {
			// 原来本身elementData容量大小 2
			int oldCapacity = elementData.length;
			// 新数据容量大小 (oldCapacity >> 1)=oldCapacity/
			int newCapacity = oldCapacity + (oldCapacity >> 1);// (2+2/2)=3
			// 如果初始容量为1的时候,那么他扩容的大小为多少呢?
			if (newCapacity - minCapacity < 0)
				newCapacity = minCapacity; // 最少保证容量和minCapacity一样
			// 将老数组的值赋值到新数组里面去
			elementData = Arrays.copyOf(elementData, newCapacity);
		}
	}

	// 使用下标获取数组元素
	public E get(int index) {
		rangeCheck(index);
		return elementData(index);
	}

	E elementData(int index) {
		return (E) elementData[index];
	}

	public E remove(int index) {
		// 1.使用下标查询该值是否存在
		E object = get(index);// index 2
		// 计算删除元素后面的长度
		int numMoved = size - index - 1; // 5
		// 2.删除原理 使用arraycopy往前移动数据,将最后一个变为空
		if (numMoved > 0)
			System.arraycopy(elementData, index + 1, elementData, index, numMoved);
		elementData[--size] = null;// 将最后一个元素变为空
		return object;
	}

	// 删除相同元素删除第一个
	public boolean remove(Object object) {
		for (int i = 0; i < elementData.length; i++) {
			Object value = elementData[i];
			if (value.equals(object)) {
				remove(i);
				return true;
			}
		}
		return false;
	}

	private void rangeCheck(int index) {
		if (index >= size)
			throw new IndexOutOfBoundsException("越界啦!");
	}

	public int getSize() {
		return size;
	}

}

最后总结

它底层使用的是数组进行增删和查询。会定义全局变量size,当增加元素时,执行size++,当删除元素时,size--。这个size就是实际的集合大小

Add方法实现原理判断实际要存放的容量是否大于elementData数组的容量。如果大于则进行扩容,若小于则进行插入。插入时,要将该下标后面的数据全部后移。

Arraylist的Get方法实现原理
根据传入的下标,到数组中进行查找。当然前提是下标值必须小于size。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值