1.ArrayList
ArrayList 底层就是⼀个 Object[] 数组
ArrayList底层数组默认初始化容量为 10
1、jdk1.8 中ArrayList 底层先创建一个长度为0的数组
2、当第一次添加元素 (调用 add0方法) 时,会初始化为一个长度为 10 的数组
当ArrayList中的容量使用完之后,则需要对容量进行扩容:
1、ArrayList 容量使用完后,会”自动”创建容量更大的数组,并将原数组中所有元素拷贝过去,这会导致效率降低2、优化:可以使用构造方法 ArrayList(int capacity)或 ensureCapacity(int capacity) 提供一个初始化容量,避免刚开始就一直扩容,造成效率较低
ArrayList构造方法:
1.ArrayList0):创建一个初始化容量为 10的空列表
2.ArrayListintinitialCapacity): 创建一个指定初始化容量为 initialCapacity 的空列表
3.ArrayList(Collection<?extends E> c): 创建一个包含指定集合中所有元素的列表
ArrayList 特点:
优点:
1.向ArrayList 未尾添加元素 (add() 方法) 时,效率较高
2.查询效率高
缺点:
1,扩容会造成效率较低(可以通过指定初始化容量,在一定程度上对其进行改善)2.另外数组无法存储大数据量(因为很难找到一块很大的连续的内存空间)3.向ArrayList 中间添加元素 (add(intindex)) ,需要移动元素,效率较低1.但是,向ArrayList 中国位置增/删元素的情况较少时不影响;2.如果增/删操作较多,可考虑改用链表。
2.Linklist
LinkedList 特点
数据结构: LinkedList 底层是一个双向链表
优点:增/删效率高
缺点:查询效率较低
LinkedList 也有下标,但是内存不一定是连续的(类似C++重载符号,将循位置访问模拟为循秩访问)LinkedList 可以调用 get(int index) 方法,返链表中第 index 个元素。
但是,每次查找都要从头结点开始遍历
add()方法源码解读
public cTass LinkedList<E> extendsimpTements...{
transient int size = 0; // 链表长度
transient Node<E> first; // 指向链表第一个节点
transient Node<E> ast; // 指向链表最后一个节点
public boolean add(E e) { // 添加元素
linkLast(e); // 向链表末尾添加元素e
return true;
}
void TinkLast(E e) { // 向链表未尾添加元素
efina1 Node<E> 1 = ast; // 暂时保存最后一个元素的指针
fina1 Node<E> newNode = new Node<>(1, e, nu11);
Tast = newNode; // newNode 作为最后一个节点
if (1 == nu11) // 当前链表为空
first = newNode; // 第一个添加的节点,即为 first
else // 链表不空
1.next = newNode; // 当前链表的最后一个节点next 指向newNodesize++;
modCount++;
}
// LinkedList 底层是一个双向链表
private static class Node<E> { // LinkedList 的节点静态内部类 Node
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;
}
Listlterator 接口
1、LinkedListadd 方法只能将数据添加到链表的未尾
2、如果要将对象添加到链表的中间位置
则需要使用 Listlterator 接口的add 方法
1.Listlterator 是 lterator 的一个子接口
3、Iterator中remove 方法
1.调用 next 之后,remove 方法删除的是迭代器左侧的元素 (类似键盘的 backspace
2.调用 previous 之后,remove 删除的是迭代器右侧的元素
4、Listlterator 中add 方法
1.调用 next 之后,在迭代器左侧添加一个元素
2.调用 previous 之后,add 是在迭代器右侧添加元素