ArrayList和LinkedList
ArrayList
ArrayList的数据结构使用的是数组,以下是ArrayList的属性。
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
private int size;
ArrayList的构造函数
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;//无参的构造函数
}
//有参的构造函数
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;//如果等于0,空数组
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
数组的就涉及到ArrayList的扩容,默认大小为10,使用一个Object数组存储数据。grow函数是ArrayList的扩容函数,每次扩容为老大小的1.5倍(int newCapacity = oldCapacity + (oldCapacity >> 1))。
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);//newCapacity =1.5*oldCapacity
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
Arrays类下的方法:
@SuppressWarnings("unchecked")
public static <T> T[] copyOf(T[] original, int newLength) {
return (T[]) copyOf(original, newLength, original.getClass());
}
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
@SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
ArrayList的常用方法
public int indexOf(Object o) //获取元素下标
public int lastIndexOf(Object o) //获取最后一个元素的下标
public E get(int index) //获取index下标的元素
public E set(int index, E element)//用指定的元素替代此列表中指定位置上的元素。
public boolean add(E e) //添加元素
public void add(int index, E element)//给下标为index赋值
public E remove(int index)//移除此列表中指定位置上的元素。
public boolean remove(Object o)//移除此列表中首次出现的指定元素(如果存在)。
@Test
public void test02(){
List<Integer> integers = new ArrayList<>();
integers.add(1);
integers.add(2);
integers.add(0);
integers.add(100);
integers.add(4,500); //添加
integers.add(5,200); //添加
integers.set(5,300);//将5位置修改为300
integers.add(6,100);
integers.add(7,100);
integers.remove(Integer.valueOf(100));//移除首次出现100的元素
System.out.println(integers);
}
LinkedList
LinkList数据结构是双向链表
transient Node<E> first;
transient Node<E> last;
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
public boolean add(E e) {
linkLast(e);
return true;
}
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
由上述linkLast,当我么创建添加第一个节点时,first=newNode,last = newNode。当我们创建第二个节点newNode2时newNode的prev为last也就是指向的是newNode,last的next指向的是newNode2,也就是newNode的next指向的是newNode2。
LinkedList的常用API
public void add(E e) //将指定元素添加到列表的尾部
public boolean remove(Object o) //从此列表中移除首次出现的指定元素(如果存在)。
public E remove(int index)//移除此列表中指定位置处的元素。
比较
ArrayList | LinkedList |
---|---|
数组 | 双向链表 |
查询快,O(1) | 增删快,查询O(n) |
连续空间 | 不需要连续空间 |
尾部插入和删除O(1) | 尾部插入和删除O(1) |