ArrayList
本篇文章是基于Java,手写ArrayList的相关内容。
该数组可实现如下方法,我们将其定义成接口:
public interface List<E> {
int size(); // 元素的数量
boolean isEmpty(); // 是否为空
boolean contains(E element); // 是否包含某个元素
void add(E element); // 添加元素到最后面
E get(int index); // 返回index位置对应的元素
E set(int index, E element); // 设置index位置的元素
void add(int index, E element); // 往index位置添加元素
E remove(int index); // 删除index位置对应的元素
int indexOf(E element); // 查看元素的位置
void clear(); // 清除所有元素
}
ArrayList的设计:
ArrayList继承于上述List
- ArrayList构造器的设计: 重点,第一次编写,不清楚构造器的构成,
public ArrayList(int capacity) {
capacity = (capacity<DEFAULT_CAPACITY)? DEFAULT_CAPACITY:size;
this.elements = (E[]) new Object[capacity];
}
public ArrayList() {
elements = (E[]) new Object[DEFAULT_CAPACITY];
}
-
定义ArrayList的属性和常量。
private int size=0; private E[] elements; private static final int DEFAULT_CAPACITY=10; private static final int ELEMENT_NOT_FOUND=-1;
-
ArrayList的私有方法:
边界检测:
private void rangeCheck(int index) { if (index < 0 || index >= size) throw new IndexOutOfBoundsException("Index:" + index + ",size:" + size); }
加法的边界检测
private void rangeCheckForAdd(int index) { if (index < 0 || index > size) throw new IndexOutOfBoundsException("Index:" + index + ",size:" + size); }
扩容函数
private void ensureCapacity(int capacity) { int oldCapacity=elements.length; if (oldCapacity>=capacity) return; int newCapacity=oldCapacity+oldCapacity>>1; Object[] newList = new Object[newCapacity]; for (int i = 0; i < size; i++) { newList[i] = elements[i]; } elements= (E[]) newList; }
tostring方法输出
@Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("size=").append(size).append(" ["); for (int i = 0; i < size; i++) { sb.append(elements[i]); if (i != size - 1) { sb.append(", "); } } sb.append("]"); return sb.toString(); }
-
实现接口的各种方法:每个方法的功能同List接口
@Override public int size() { return size; } @Override public boolean isEmpty() { return size==0; } @Override public boolean contains(Object element) { return indexOf(element)!=ELEMENT_NOT_FOUND; } @Override public void add(Object element) { add(size,element); } @Override public Object get(int index) { rangeCheck(index); return elements[index]; } @Override public Object set(int index, Object element) { rangeCheck(index); E old = elements[index]; elements[index]= (E) element; return old; } @Override public void add(int index, Object element) { rangeCheckForAdd(index); ensureCapacity(size+1); for (int i = size-1; i >=index; i--) { elements[i + 1] = elements[i]; } elements[index]= (E) element; size++; } @Override public Object remove(int index) { rangeCheck(index); E old = elements[index]; for (int i = index+1; i < size; i++) { elements[i - 1] = elements[i]; } size--; return old; } @Override public int indexOf(Object element) { if (element == null) { return ELEMENT_NOT_FOUND; } else { for (int i = 0; i < size; i++) { if (element.equals(elements[i])) return i; } return ELEMENT_NOT_FOUND; } } @Override public void clear() { size=0; }
-
测试结果
@Test public void test01() { ArrayList<Integer> list = new ArrayList<>(); list.add(1); list.add(0,2); list.add(list.size(),10); Integer o = (Integer)list.get(0); list.remove(0); System.out.println(list); System.out.println(o); }
-
小结:ArryList的编写重点
- 构造器的设计
- 边界检测要分为添加和一般情况。
- 添加和删除要注意循环方向,和循环位置。
- 添加扩容时,容易出错。不清楚