Java-手写ArrayList集合

1.Arraylist数组存储对象实现原理

Jdk1.8源代码中

Java-手写ArrayList集合_第1张图片

其实ArrayList是用Object[]数组实现。

这里我们有些轮子也不用完全自己造了,可以参考jdk源码,实现核心代码即可。

2.首先介绍ArrayList中的几个核心方法原理

2.1添加元素

普通添加,list.add(Object),元素添加在数组的最后

Java-手写ArrayList集合_第2张图片

在指定脚标位置添加元素,list.add(index,Object),如果在脚标3的位置插入,则4以后的元素全部往后移动一位

Java-手写ArrayList集合_第3张图片

2.2删除元素

list.remove(Object),删除位置为4的元素,则4以后的元素全部往前移动一位

Java-手写ArrayList集合_第4张图片

2.3数组扩容

Object[]数组是有默认大小的,如果添加的元素长度超过数组长度,需要进行扩容。

jdk1.8扩容机制为原来长度的1.5倍,>>1 位移符 可以理解为*0.5

Java-手写ArrayList集合_第5张图片

Java-手写ArrayList集合_第6张图片

3.实现源代码

本文中只实现,add(),remove(),get()等基本方法。

package com.huajie.arrayList;

import java.util.AbstractList;
import java.util.Arrays;

/**
 * 手写arraylist 数组集合
 * 1.扩容技术 1.5倍
 * 2.数组复制
 * 与vertor区别  vertor线程安全 但是效率慢 操作方法都加了 同步 ,扩容2倍 
 * @author xiewenfeng
 *
 * @param 
 */
public final class XwfArrayList extends AbstractList {
	// 底层采用数据存放
	private Object[] elementData;
	// 默认空数组
	private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
	// 默认数组容量
	private static final int DEFAULT_CAPACITY = 2;
	// 时间ArrayList大小
	private int size;

	public XwfArrayList(int initialCapacity) {
		// 初始容量
		if (initialCapacity > 0) {
			elementData = new Object[initialCapacity];
		} else if (initialCapacity == 0) {
			elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
		} else {
			throw new RuntimeException("创建数组初始长度不能为负数");
		}
	}

	/**
	 * JDK1.7之后 初始化 放在 ADD方法里面
	 */
	public XwfArrayList() {
		elementData = new Object[DEFAULT_CAPACITY];
	}

	public boolean add(Object obj) {
		// 扩容
		ensureExplicitCapacity(size + 1);
		// 2.使用下标赋值
		elementData[size++] = obj;
		return true;
	}

	/**
	 * 扩容
	 * 
	 * @param minCapacity
	 */
	private void ensureExplicitCapacity(int minCapacity) {
		// 1.判断容量
		if (size == elementData.length) {
			int oldCapacity = size;
			int newCapacity = oldCapacity + (oldCapacity >> 1);
			// 初始最小容量
			if (newCapacity - minCapacity < 0) {
				newCapacity = minCapacity;
			}
			elementData = Arrays.copyOf(elementData, newCapacity);
		}
	}

	@SuppressWarnings("unchecked")
	public E get(int index) {
		rangeCheck(index);
		return (E) elementData[index];
	}

	private void rangeCheck(int index) {
		if (index >= size)
			throw new IndexOutOfBoundsException("数组脚标越界");
	}

	public int size() {
		return size;
	}

	public E remove(int index) {
		rangeCheck(index);
		// 拿到要删除的数据
		E object = get(index);
		// 需要复制的长度 index后面
		int numMoved = size - index - 1;
		// 从第几位开始复制 index+1
		int srcPos = index + 1;
		// 移动到第几位
		int destPos = index;
		if (numMoved > 0) {
			System.arraycopy(elementData, srcPos, elementData, destPos, numMoved);
		}
		// 最后一位删除
		elementData[--size] = null;
		return object;
	}

	/**
	 * 删除对象
	 * 
	 * @param obj
	 * @return
	 */
	public boolean remove(Object obj) {
		for (int i = 0; i < elementData.length; i++) {
			Object value = elementData[i];
			if (value.equals(obj)) {
				remove(i);
				return true;
			}
		}
		return false;
	}

	/**
	 * 插入对象
	 * 
	 * @param obj
	 * @return
	 */
	public void add(int index, Object obj) {
		rangeCheck(index);
		// 扩容
		ensureExplicitCapacity(size + 1);
		// 复制数组后移一位
		System.arraycopy(elementData, index, elementData, index + 1, size - index);
		// 2.使用下标赋值
		elementData[index] = obj;
		size++;
	}

	/**
	 * 清空数组
	 */
	public void clear() {
		for (int i = 0; i < elementData.length; i++) {
			elementData[i] = null;
		}
		size = 0;
	}
}

代码中有两段取自jdk源码实现,可以用其他代码实现,jdk源码中的效率更高

第一段:

Java-手写ArrayList集合_第7张图片

扩容的复制数组,可以用以下代码替换

Object[] old = elementData;
elementData = new Object[newCapacity];
for (int i = 0; i < size; i++) {
  elementData[i] = old[i];
}

第二段:

Java-手写ArrayList集合_第8张图片

数组向后移动一位,可以用以下代码替换

for (int i = size; i > index; i--) {
			elementData[i] = elementData[i-1];
		}

同理还有remove中的,如果使用原始的for循环,系统开销比较大。

4.测试

package com.huajie.arrayList;

public class Test001 {
	public static void main(String[] args) {
		XwfArrayList a = new XwfArrayList();
		a.add("haha1");
		a.add("haha2");
		a.add("haha3");
		a.add("haha4");
		a.add("haha5");
		for (int i = 0; i < a.size(); i++) {
			System.out.println(a.get(i));
		}
		System.out.println("==========================");
		Object remove = a.remove(2);
		System.out.println("删除的元素" + remove);
		for (int i = 0; i < a.size(); i++) {
			System.out.println(a.get(i));
		}
		System.out.println("==========================");
		a.add(2, "新插入");
		for (String string : a) {
			System.out.println(string);
		}
	}
}

Java-手写ArrayList集合_第9张图片

你可能感兴趣的:(数据结构)