一、 数组复制方法
System.arraycopy()
public static native void arraycopy(Object src, int srcPos, Object dest, int destPos,int length);
src - 源数组。
srcPos - 源数组中的起始位置。
dest - 目标数组。
destPos - 目标数据中的起始位置。
length - 要复制的数组元素的数量
Arrays.copyOf()
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
@SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
- original - 要复制的数组
- newLength - 要返回的副本的长度
- newType - 要返回的副本的类型
可以看出在Arrays.copyOf()中先是创建了一个新的内部数组,长度为传入的newLength ,然后再通过System.arraycopy()将原数组的值全部复制到新数组,并返回新数组
二、ArrayList内部图
![](https://github.com/AlgoricLi/MyImage/blob/master/Collection/ArrayList%E5%86%85%E5%AD%98%E5%9B%BE.png?raw=true)
![](https://github.com/AlgoricLi/MyImage/blob/master/Collection/ArrayList%E6%95%B0%E7%BB%84%E5%86%85%E5%AD%98%E5%9B%BE.png?raw=true)
手写ArrayList
定义抽象类
public interface SelfList<E> {
void add(E e);
int size();
E get(int index);
E remove(int index);
}
实现主体
public class SelfArrayList<E> implements SelfList<E> {
//底层使用数组存储
private Object[] data = {};
//数组初始分配的长度
private static final int capacity = 10;
//数组实际元素数量
private int size;
@Override
public void add(E e) {
//判断是否扩容及一系列处理
ensureCapacityInternal(size + 1);
//加入数组
data[size++] = e;
}
public void add(int index, E e) {
rangeCheck(index);
ensureCapacityInternal(size + 1);
System.arraycopy(data, index, data, index + 1, size - index);
data[index] = e;
size++;
}
@Override
public int size() {
return size;
}
@Override
public E get(int index) {
rangeCheck(index);
return (E) data[index];
}
@Override
public E remove(int index) {
rangeCheck(index);
E item = (E) data[index];
if(item == null) {
throw new RuntimeException("该元素不存在");
}
int removeLength = size - index -1;
//最后一个没必要移动数组,损耗性能
if(removeLength > 0)
System.arraycopy(data, index + 1, data, index, removeLength);
data[size--] = null;
return item;
}
public boolean remove(E e) {
if(e == null) {
for(int i =0; i< size; i++) {
if(data[i] == null ) {
remove(i);
return true;
}
}
} else {
for(int i =0; i< size; i++) {
if(data[i].equals(e) ) {
remove(i);
return true;
}
}
}
return false;
}
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException("越界啦!");
}
/**
* 数组是否扩容
* @param minCapacity
*/
private void ensureCapacityInternal(int minCapacity) {
//初始化数组长度
if(data.length == 0) {
minCapacity = capacity;
expansion(minCapacity);
}
//最小容量大于数组长度 扩容
if(minCapacity - data.length < 0) {
expansion(minCapacity);
}
}
/**
* 数组扩容
* @param
*/
private void expansion(int minCapacity) {
int oldCapacity = data.length;
int newCapacity = oldCapacity + (oldCapacity << 1);
//扩容后数组长度比最小容量还小,将最小容量赋值给新数组
if(newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
// System.arraycopy(data, 0, data, 0, newCapacity);
data = Arrays.copyOf(data, newCapacity);
}
}
ArrayList的代码比较简单,底层是通过数组实现。
-
new一个ArrayList对象时,会创建一个空数组,只有第一次加载才会分配容量为10
-
当数组容量不够,需要扩容,int newCapacity = oldCapacity + (oldCapacity << 1),每次扩容1.5倍
-
插入元素,会引起数组的移动,每次需要创建一个新数组,将数组index(包括)后面元素整体向后移动一位,空出来的位置放入待插入的元素
-
删除指定元素和上面同理,将index(不包括)后面元素整体向前移动一位,同时放入新数组。remove是根据equals方法来寻找元素的,可以通过改写equals方法指定删除自定义认为相同的元素。