手写ArrayList集合:MyArrayList
文章目录
前言
查看源代码可以帮助我们快速提高程序员的编程素养。了解底层运作的原理。所以要学会分析底层的代码,锻炼自己的分析能力。
提示:以下是本篇文章正文内容:
一、主要功能:
二、代码实现:
1.MyConsumer函数式接口:
@FunctionalInterface
public interface MyConsumer<E> {
void accept(E e);
}
2.MyArrayList类:
import java.util.Arrays;
import java.util.Objects;
public class MyArrayList<E> {
private Object[] elementData = {};//内部使用数组做容器
private int size;//元素个数
private int DEFAULT_CAPACITY = 10;//默认容量
public boolean add(E e) {
//注意7:先判断是否需要扩容
if (size == elementData.length) {
grow();
}
elementData[size++] = e;
return true;
}
public E remove(int index) {
//先检查索引
checkIndex(index);
E e = (E) elementData[index];
//注意6:计算需要“移位”的个数:5 - 4 - 1 == 0
int moveNum = size - index - 1;
if (moveNum != 0) {
//注意3:将index+1后的movenum个元素往前移动一位。
System.arraycopy(elementData, index + 1, elementData, index, moveNum);
}
elementData[--size] = null;
return e;
}
public E get(int index) {
checkIndex(index);
return (E) elementData[index];
}
public int size() {
return size;
}
public void forEach(MyConsumer<E> action) {
//注意4:检查集合是否为null:如果是,抛出空指针异常
Objects.requireNonNull(action);
for (int i = 0; i < size; i++) {
action.accept((E) elementData[i]);
}
}
private void checkIndex(int index) {
//注意2:如果index越界,就抛出异常,有“前后界”。
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException(index + " out of max length " + size);
}
}
private void grow() {
//1.第一次扩容
if (size == 0) elementData = new Object[DEFAULT_CAPACITY];
//2.其他
//注意1:1+(1>>2) = 1.5
else elementData = Arrays.copyOf(elementData, elementData.length + (elementData.length >> 2));
}
//注意5:重写tostring方法,按照合适的格式在,控制台展示数据。
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < size; i++) {
E e = (E) elementData[i];
sb.append(e).append(i == size - 1 ? "" : ", ");
}
sb.append("]");
return sb.toString();
}
}
3.测试类:
三、注意点:
1.扩容
2.索引越界判断
3.移位
4.lambda表达式
5.函数式接口
6.抛异常
7.合适的tostring方法
四、与官方代码相比较:
扩容,检查索引范围,删除元素,遍历,添加元素
总结
提示:这里对文章进行总结:
多看,多分析,多理解,多实现。