ArrayList
ArrayList是一个其容量能够动态增长的动态数组。它继承了AbstractList,实现了List、RandomAccess, Cloneable, java.io.Serializable。
基本的ArrayList,长于随机访问元素,但是在List中间插入和移除元素时较慢。
ArrayList有三种遍历方式
分别是索引值遍历,迭代器遍历还有for循环遍历
遍历ArrayList时,通过索引值遍历效率最高,for循环遍历次之,迭代器遍历最低。
ArrayList源码解析
类成员
// 序列版本号
private static final long serialVersionUID = 8683452581122892189L;
// 默认容量大小
private static final int DEFAULT_CAPACITY = 10;
// 空数组
private static final Object[] EMPTY_ELEMENTDATA = {};
// 用于保存ArrayList中数据的数组
private transient Object[] elementData;
// ArrayList中所包含元素的个数
private int size;
//数组的最大容量
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
构造函数
//初始为空数组
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;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
//直接创建和指定集合一样内容的 ArrayList
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray 有可能不返回一个 Object 数组
if (elementData.getClass() != Object[].class)
//使用 Arrays.copy 方法拷创建一个 Object 数组
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
扩容方法
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
// 1.5 倍 原来容量
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果当前容量还没达到 1.5 倍旧容量,就使用当前容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
//最大容量可以是 Integer.MAX_VALUE
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
ArrayList常用方法
add
public boolean add(E e) {
//对数组的容量进行调整
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
//在指定位置添加一个元素
public void add(int index, E element) {
rangeCheckForAdd(index);
//对数组的容量进行调整
ensureCapacityInternal(size + 1); // Increments modCount!!
//整体后移一位
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
//添加一个集合
public boolean addAll(Collection<? extends E> c) {
//把该集合转为对象数组
Object[] a = c.toArray();
int numNew = a.length;
//增加容量
ensureCapacityInternal(size + numNew); // Increments modCount
//挨个向后迁移
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
//新数组有元素,就返回 true
return numNew != 0;
}
查询,修改等操作
E elementData(int index) {
return (E) elementData[index];
}//根据下标返回值
//获取
public E get(int index) {
rangeCheck(index);
//直接根据数组角标返回元素
return elementData(index);
}
//修改
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
//直接对数组操作
elementData[index] = element;
//返回原来的值
return oldValue;
}
删除操作
//根据下标删除
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
//挨个往前移一位
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//原数组中最后一个元素删掉
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
//根据值删除
public boolean remove(Object o) {
if (o == null) {
//挨个遍历找到目标
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
//快速删除
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; //
}
//清楚全部
public void clear() {
modCount++;
//并没有直接使数组指向 null,而是逐个把元素置为空
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
Toarray方法
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
public <T> T[] toArray(T[] a) {
//如果只是要把一部分转换成数组
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
//全部元素拷贝到 数组 a
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
其他的一些方法
//返回长度
public int size() {
return size;
}
//判断是否为空
public boolean isEmpty() {
return size == 0;
}
//判断是否存在某个元素
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
// 返回某个元素的下标
public int indexOf(Object o) {
//先判断o是否为空,再根据情况进行遍历整个ArrayList
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
LinkedList
LinkedList是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。
LinkedList 实现 List 接口,Deque接口,Cloneable接口,java.io.Serializable接口
成员变量
//LinkedList中元素的数量
transient int size = 0;
//第一个元素
transient Node<E> first;
//最后一个元素
transient Node<E> last;
构造函数
public LinkedList() {
}
//有参构造
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
插入方法
public boolean addAll(int index, Collection<? extends E> c) {
checkPositionIndex(index);
//把c转化成数组
Object[] a = c.toArray();
int numNew = a.length;
//如果数组中没有元素,返回false
if (numNew == 0)
return false;
Node<E> pred, succ;
if (index == size) {
//如果index为size,那么index位置上的node为null,node的前一个节点是last
succ = null;
pred = last;
} else {
//找到当前index位置上的node,用succ表示。pred表示当前节点的前一个节点
succ = node(index);
pred = succ.prev;
}
for (Object o : a) {
@SuppressWarnings("unchecked") E e = (E) o;
Node<E> newNode = new Node<>(pred, e, null);
if (pred == null)
first = newNode;
else
pred.next = newNode;
pred = newNode;
}
if (succ == null) {
last = pred;
} else {
pred.next = succ;
succ.prev = pred;
}
size += numNew;
modCount++;
return true;
}
//上面的方法就是把c中所有的元素插入LinkList
//将元素添加到第一个位置
public void addFirst(E e) {
linkFirst(e);
}
//将元素添加到最后
public void addLast(E e) {
linkLast(e);
}
//add方法和addlast差不多
public boolean add(E e) {
linkLast(e);
return true;
}
//将元素添加到指定位置
public void add(int index, E element) {
//检查合法性
checkPositionIndex(index);
//如果是添加在最后一个位置,直接调用linkLast
if (index == size)
linkLast(element);
else
//如果不是的话就需要调用linkBefore
linkBefore(element, node(index));
}
//头插法
private void linkFirst(E e) {
final Node<E> f = first;
final Node<E> newNode = new Node<>(null, e, f);
first = newNode;
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}
//尾插法
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++;
}
获取值的方法
//得到第一个元素
public E getFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return f.item;
}
//得到最后一个元素
public E getLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return l.item;
}
//根据下标获取
public E get(int index) {
//检查下标合法性
checkElementIndex(index);
return node(index).item;
}
//
删除方法
//根据下标删除
public E remove(int index) {
//先检查下标合法性
checkElementIndex(index);
//直接先调用node获取到节点,然后用unlink删除掉
return unlink(node(index));
}
//根据值来删除
public boolean remove(Object o) {
//根据不同情况进行比较
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) {
unlink(x);
return true;
}
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
//删除最后一个元素
public E removeLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return unlinkLast(l);
}
//删除第一个元素
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
//删除第一个元素
public E poll() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
}
//删除第一个元素
public E remove() {
return removeFirst();
}
//清空操作
public void clear() {
for (Node<E> x = first; x != null; ) {
//获得某个节点的下一个节点之后就清除此节点的所有信息
Node<E> next = x.next;
x.item = null;
x.next = null;
x.prev = null;
x = next;
}
first = last = null;
size = 0;
modCount++;
}
其他方法
//判断是否存在某个元素
public boolean contains(Object o) {
return indexOf(o) != -1;
}
//通过传入的元素查找下标
public int indexOf(Object o) {
int index = 0;
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null)
return index;
index++;
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item))
return index;
index++;
}
}
return -1;
}
ArrayList是基于数组实现的,LinkedList是基于链表实现的
ArrayList便于查询,在插入和删除的时候效率较低
LinkedList便于插入和删除,但是查询时效率较低