概述
- 线性表是具有N个相同类型元素的有序集合(n >= 0)

2. 常见的线性表
- 数组
- 链表
- 队列
- 栈
- 哈希表
线性表之数组 (Array)
- 数组是一种顺序存储的线性表,所有元素的内存地址是连续的。
int[] array = new int[]{11, 22, 33} Java中声明数组
- 在内存中的表示

4. 可以看到 11,22,33 的内存是连续存储的。
动态数组、接口设计
int size():获取元素的数量
boolean isEmpty():判断数组是否为空
boolean contains(E element):是否包含某个元素
void add(E element):添加元素到数组的末尾
E get(int index):获取某个元素
E set(int index, E element):设置idnex位置的元素
void add(int index, E element):把元素添加到index位置
E remove(int index):删除元素
int indexOf(E element):查看元素的位置
void clear():请空所有元素
删除元素思路
- 如果删除的是中间元素,我们需要对
size--,并且后面的元素依次向前移动,并且将最后一个元素,设置为 null即可

2. 如图,删除index=3的元素,需要把 4 5 6 元素向前挪动
在指定位置添加元素
- 如图:如果在索引2处添加元素,则需要将所以 2、3、4的元素向后挪动,将索引2的地方空出来
- 这里要注意,移动顺序需要从最后一个元素,依次递减移动。
动态数组,如何扩容
- 当内部数组容量满时,无法再后面追加连续的内存,只能重新
new 申请一个更大的数组,然后将原有的元素挪动到新的数组中。
- 然后将原有的引用执行新的数组。
最终实现
public class ArrayList<E> {
private int size;
private E[] elements;
private static final int DEFAULT_CAPACITY = 10;
private static final int ELEMENT_NOT_FOUND = -1;
public ArrayList() {
this(DEFAULT_CAPACITY);
}
public ArrayList(int capacity) {
capacity = capacity < DEFAULT_CAPACITY ? DEFAULT_CAPACITY : capacity;
elements = (E[]) new Object[capacity];
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public boolean contains(E element) {
return indexOf(element) != ELEMENT_NOT_FOUND;
}
public E get(int index) {
rangeCheck(index);
return elements[index];
}
public E set(int index, E element) {
rangeCheck(index);
E old = elements[index];
elements[index] = element;
return old;
}
public void add(E element) {
ensureCapacity(size + 1);
elements[size++] = element;
}
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacity(size + 1);
int movedLen = size - index;
if (movedLen > 0) {
System.arraycopy(elements, index, elements, index + 1, movedLen);
}
elements[index] = element;
size++;
}
public E remove(int index) {
rangeCheck(index);
E old = elements[index];
int movedLen = size - index - 1;
if (movedLen > 0)
System.arraycopy(elements, index + 1, elements, index, movedLen);
elements[--size] = null;
return old;
}
public int indexOf(E element) {
if (element == null) {
for (int i = 0; i < size; i++) {
if (elements[i] == null)
return i;
}
} else {
for (int i = 0; i < size; i++) {
if (element.equals(elements[i]))
return i;
}
}
return ELEMENT_NOT_FOUND;
}
public void clear() {
for (int i = 0; i < size; i++) {
elements[i] = null;
}
size = 0;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < size; i++) {
if (i != 0) {
sb.append(", ");
}
sb.append(elements[i].toString());
}
sb.append("]");
return sb.toString();
}
private void ensureCapacity(int capacity) {
int oldCapacity = elements.length;
if (oldCapacity >= capacity)
return;
int newCapacity = oldCapacity + (oldCapacity >> 1);
elements = Arrays.copyOf(elements, newCapacity);
System.out.println("旧容量:" + oldCapacity + ",新容量:" + newCapacity);
}
private void rangeCheck(int index) {
if (index < 0 || index >= size) {
outOfBounds(index);
}
}
private void rangeCheckForAdd(int index) {
if (index < 0 || index > size) {
outOfBounds(index);
}
}
private void outOfBounds(int index) {
throw new IndexOutOfBoundsException("Index: " + index + ", size:" + size);
}
}