表List是一种一维的数据结构,底层有两种实现方式,分别是基于数组实现的ArrayList和基于链表实现的LinkedList。ArrayList具有读取快(get),插入删除慢(add、remove)的特点;而LinkedList在知道插入删除的位置时,具有插入删除快(add、remove),而读取慢(get)的特点。
一、基于数组的实现
下面的代码是基于数组实现的一个List。
import java.util.Iterator;
import java.util.NoSuchElementException;
public class MyArrayList<Item> implements Iterable<Item> {
private static final int DEFAULT_CAPACITY = 10;
private Item[] items;
private int size;
public MyArrayList() {
clear();
}
public void add(Item item) {
add(size, item);
}
public void add(int i, Item item) {
if(i < 0 || i > size)
throw new ArrayIndexOutOfBoundsException();
if(size == items.length) {
ensureCapacity(size * 2 + 1);
}
for(int j=size;j>i;j--) {
items[j] = items[j-1];
}
items[i] = item;
size++;
}
public Item remove(int i) {
if(i < 0 || i >= size)
throw new ArrayIndexOutOfBoundsException();
Item item = items[i];
for(int j=i;j<size-1;j++) {
items[j] = items[j+1];
}
items[size-1] = null;
size--;
if(size < items.length/4 && items.length/2 > DEFAULT_CAPACITY)
ensureCapacity(items.length/2);
return item;
}
public Item set(int i, Item item) {
if(i < 0 || i >= size)
throw new ArrayIndexOutOfBoundsException();
Item old = items[i];
items[i] = item;
return old;
}
public Item get(int i) {
if(i < 0 || i >= size)
throw new ArrayIndexOutOfBoundsException();
return items[i];
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public void clear() {
size = 0;
ensureCapacity(DEFAULT_CAPACITY);
}
public void trimToSize() {
ensureCapacity(size);
}
private void ensureCapacity(int capacity) {
if(capacity < size)
return;
Item[] old = items;
items = (Item[])new Object[capacity];
for(int i=0;i<size;i++) {
items[i] = old[i];
}
}
public Iterator<Item> iterator() {
return new MyArrayListIterator();
}
private class MyArrayListIterator implements Iterator<Item> {
int current = 0;
public boolean hasNext() {
return current < size;
}
public Item next() {
if(!hasNext())
throw new NoSuchElementException();
return items[current++];
}
}
}
二、基于链表的实现
下面是基于双向链表的实现。为了便于特殊情况的处理,在链表的首尾两端各自添加了一个起标记作用的哑节点。
import java.util.Iterator;
import java.util.NoSuchElementException;
public class MyLinkedList<Item> implements Iterable<Item> {
private int size;
private Node startMarker;
private Node endMarker;
private class Node {
Item item;
Node prev;
Node next;
Node(Item item, Node prev, Node next) {
this.item = item;
this.prev = prev;
this.next = next;
}
}
public MyLinkedList() {
startMarker = new Node(null, null, null);
endMarker = new Node(null, startMarker, null);
startMarker.next = endMarker;
size = 0;
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public void add(Item item) {
add(size, item);
}
public void add(int i, Item item) {
Node n = getNode(i, 0, size);
addBefore(n, item);
}
private void addBefore(Node n, Item item) {
Node newNode = new Node(item, n.prev, n);
newNode.prev.next = newNode;
n.prev = newNode;
size++;
}
public Item get(int i) {
return getNode(i).item;
}
private Node getNode(int i) {
return getNode(i, 0, size-1);
}
private Node getNode(int i, int low, int high) {
if(i < low || i > high)
throw new IndexOutOfBoundsException();
Node n;
if(i < size/2) {
n = startMarker.next;
for(int j=0;j<i;j++) {
n = n.next;
}
} else {
n = endMarker;
for(int j=size;j>i;j--) {
n = n.prev;
}
}
return n;
}
public Item set(int i, Item newItem) {
Node n = getNode(i);
Item old = n.item;
n.item = newItem;
return old;
}
public Item remove(int i) {
Node n = getNode(i);
return remove(n);
}
private Item remove(Node n) {
n.prev.next = n.next;
n.next.prev = n.prev;
size--;
return n.item;
}
public void clear() {
startMarker.next = endMarker;
endMarker.prev = startMarker;
size = 0;
}
public Iterator<Item> iterator() {
return new Iterator<Item>() {
Node current = startMarker.next;
public boolean hasNext() {
return current != endMarker;
}
public Item next() {
if(!hasNext())
throw new NoSuchElementException();
Item item = current.item;
current = current.next;
return item;
}
};
}
}