ArrayList和LinkedList比较分析:
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
4.ArrayList需要连续的存储空间,空间利用率较低,LinkedList空间利用率较高。
LinkedList图示(具体逻辑请参看代码和算法导论):
代码实现:
package 表;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;
// 带哨兵的双向循环链表
public class LinkedList<T> implements List<T>, Iterable<T> {
// 节点类
@SuppressWarnings("hiding")
private class Node<T> {
Node<T> pre;
Node<T> next;
T key;
Node() {
this.pre = this;
key = null;
this.next = this;
}
Node(Node<T> pre, T key, Node<T> next) {
this.pre = pre;
this.key = key;
this.next = next;
}
}
private int size = 0; // 表中元素的数量
private Node<T> guard = new Node<>(); // 哨兵节点
private int modCount = 0; // 记录list修改次数
// 在表末尾加入元素
@Override
public void add(T obj) {
add(size, obj);
}
// 在指定index处加入元素,如果index超出表范围,抛出异常
@Override
public void add(int index, T obj) {
size = size + 1;
Node<T> node = getNode(index);
Node<T> newNode = new Node<>(node.pre, obj, node);
node.pre.next = newNode;
node.pre = newNode;
modCount++;
}
// 删除链表中给定位置的元素,如果index超出表范围,抛出异常
@Override
public void remove(int index) {
Node<T> node = getNode(index);
node.pre.next = node.next;
node.next.pre = node.pre;
size--;
modCount++;
}
// 删除表中遇到的第一个给定元素的值,如果表改变,则返回true,否则返回false
@Override
public boolean remove(T obj) {
Node<T> node = guard.next;
while(!node.key.equals(obj) && node.next != guard)
node = node.next;
if(node.key.equals(obj)) {
node.pre.next = node.next;
node.next.pre = node.pre;
size--;
modCount++;
return true;
}
return false;
}
// 修改index处值为obj,如果index超出表范围,抛出异常
@Override
public void set(int index, T obj) {
Node<T> node = getNode(index);
modCount++;
node.key = obj;
}
// 返回子list
@Override
public List<T> subList(int fromIndex, int lastIndex) {
if(fromIndex < 0 || fromIndex > lastIndex || lastIndex > size)
throw new IndexOutOfBoundsException();
Node<T> from = getNode(fromIndex);
List<T> result = new LinkedList<>();
while(fromIndex < lastIndex) {
result.add(from.key);
from = from.next;
fromIndex++;
}
return result;
}
// 返回index处的值,如果index超出表范围,抛出异常
@Override
public T get(int index) {
check(index);
return getNode(index).key;
}
// 返回index处节点,如果index超出表范围,抛出异常
private Node<T> getNode(int index) {
check(index);
Node<T> node = guard.next;
for(int i = 0; i < index; i++)
node = node.next;
return node;
}
// 返回表中元素个数
@Override
public int size() {
return size;
}
// 判断表是否为空
@Override
public boolean isEmpty() {
return size == 0;
}
// 清空表中元素
@Override
public void clear() {
// 清空表中对象
for(Node<T> node = guard.next; node != guard;) {
Node<T> delete = node;
node = node.next;
delete.pre = null;
delete.key = null;
delete.next = null;
}
guard.next = guard;
guard.pre = guard;
size = 0;
modCount++;
}
// 返回迭代器
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
private int index = 0;
private int expectModCount = modCount;
@Override
public boolean hasNext() {
return index < size;
}
@Override
public T next() {
checkForModification();
if(!hasNext())
throw new NoSuchElementException();
Node<T> result = getNode(index);
index++;
return result.key;
}
private void checkForModification() {
if(expectModCount != modCount)
throw new ConcurrentModificationException();
}
};
}
// 判断表中是否包含obj值
@Override
public boolean contains(T obj) {
return indexOf(obj) != -1;
}
// 返回第一个值等于obj的index,如果表中不包含值obj,返回-1
@Override
public int indexOf(T obj) {
Node<T> node = guard.next;
int index = 0;
while(node != guard && !node.key.equals(obj)) {
node = node.next;
index++;
}
if(node != guard)
return index;
return -1;
}
// 返回最后一个值等于obj的index,如果表中不包含值obj,返回-1
@Override
public int lastIndexOf(T obj) {
Node<T> node = guard.pre;
int index = size - 1;
while(node != guard && !node.key.equals(obj)) {
node = node.pre;
index--;
}
return index;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("[");
Node<T> next = guard.next;
while(next != guard) {
sb.append(next.key + ", ");
next = next.next;
}
sb.delete(sb.length() - 2, sb.length());
sb.append("]");
return sb.toString();
}
// 测试index是否超出表的范围,如果超出,抛出异常
private void check(int index) throws IndexOutOfBoundsException{
if(index >= size)
throw new IndexOutOfBoundsException();
}
}
代码测试:
package 表;
public class TestList {
public static void main(String[] args) {
Integer[] iarray = new Integer[20];
for(int i = 0; i < iarray.length; i++)
iarray[i] = i;
List<Integer> list = new LinkedList<>();
// 测试add方法
for(Integer i : iarray)
list.add(i);
System.out.println(list);
list.add(2, 10);
System.out.println(list);
// 测试remove方法
list.remove(2);
System.out.println(list);
list.remove(new Integer(10));
System.out.println(list);
// 测试set方法
list.set(2, 11);
System.out.println(list);
// 测试subList
System.out.println(list.subList(2, 10));
// 测试get
System.out.println(list.get(18));
// 测试indexOf, lastIndexOf
System.out.println("indexOf(): " + list.indexOf(11) +
" lastIndexOf(): " + list.lastIndexOf(11));
System.out.println("indexOf(): " + list.indexOf(111) +
" lastIndexOf(): " + list.lastIndexOf(111));
// 测试contains
System.out.println("contains(4): " + list.contains(4) +
" contains(100): " + list.contains(100));
// 测试迭代器
for(Integer i : list) {
System.out.print(i + " ");
// list.add(2 * i); // 去掉注释会抛出异常,在迭代器调用时,不允许修改list
}
System.out.println();
// 测试size,clear,isEmpty
System.out.println("size(): " + list.size() + " isEmpty(): " + list.isEmpty());
list.clear();
System.out.println("调用clear()后\nsize(): " + list.size() +
" isEmpty(): " + list.isEmpty());
}
}