java集合
1. 集合关系图
集合接口
terface.png)
实现类
2. LinkedList与ArrayList
2.1常用api,迷惑看https://docs.oracle.com/javase/7/docs/api/
构造
ArrayList() 构造一个初始容量为0的空列表,官方文档上说是10, 我认为不正确。源码中构造函数中数组指针指向一了空数组,尽管size字段在申明时初始化为10, 但是不代表构造完成后数组大小为10。当插入元素时才开始扩容为10。
int[] array = {}; // 等价与int[] array = new int[0]
// array长度为0,但是不为null
// null表示这个变量指向的对象为不存在,还没有给对象分配内存空间
// 此处的array指向了一个对象,只不过这个对象数组长度为零罢了。
ArrayList(Collection extends E>) 构造一个包含集合的元素,按照他们由集合迭代器返回的顺序构建ArrayList。如果集合内的元素Class一样,也就是说类型一样,直接指向Collection。如果是子类,利用Arrays.copy()复制,进行类型强转。
ArrayList(int initailCapacity) 构造具有初始容量的ArrayList,一般而言,如果事先知道有多少个元素,最好指定容量,避免不必要的resize()。尽管数组容量不为0, 但是有效元素个数size为0!!!
增
boolean add(E e) 增加元素到列表末尾
boolean add(int index, E element) 在索引index前面插入element。
List array = ArrayList(10);
array.add(2, 5);
// 上面的代码出现数组越界异常
// 我以为声明了10个空间大小,每个初始化为0,所以我可以这么干啊。
// 尽管声明了大小为10的数组,但是size = 0, size为有效元素的个数。
// add()是针对下标在0-size-1之间的数组。
boolean addAll(Collection extends E>) Collectin加到arraylist尾部
删
boolean remove(int index) 删除index下标,当然了,index也必须时在0-size-1之间
boolean remove(Object 0) 删除第一个元素0,内部使用equals()比较
// 贴一段我觉得写得很棒的代码
// 如果我实现下面的逻辑,肯定是return到处扔,肯定要把break换成fastRemove(es, i)和return true
// 要是需求变了,要求remove失败返回true, 那就拉胯了。
public boolean remove(Object o) {
final Object[] es = elementData;
final int size = this.size;
int i = 0;
found: {
if (o == null) {
for (; i < size; i++)
if (es[i] == null)
break found;//跳出found
} else {
for (; i < size; i++)
if (o.equals(es[i]))
break found;//跳出found
}
return false;
}
fastRemove(es, i);
return true;
}
改
E set(int index, E element) 返回原来的值
查
E get(int index)
其他
int size() 有效元素个数
int indexOf(Object o) 返回元素下标, 内部使用equals比较大小
Iteratoriterator() 返回迭代器
Object clone()返回浅拷贝arrayList()
contains(Object o) 内部使用equeals()
Object[] toArray() 返回对应的数组
LinkedList, 除了ArrayList的一些操作,还可以当栈,队列,双端队列,所以api要多一点
构造函数
LinkList()
LinkList(Collection extend E> c)
增
boolean addFirst(E e) boolean addLast(E e) 双端队列常用操作
add(E e) 队尾部加
删
E remove() 删除第一个节点
E removeFirst()
E removeLast()
E poll() 删除第一个节点
E pollFirst()
E pollLast()
改
set(in index)
查看
E peek() 获得第一个元素
E peekFirst() 获得第一个元素
E peekLast() 获得最后一个元素
E getFirst()
E getLast()
2.2 内部实现分
ArrayList : 可扩容的动态数组
线程不同步。
默认初始容量为 10,当数组大小不足时容量扩大为 1.5 倍。
为追求效率,ArrayList 没有实现同步(synchronized),如果需要多个线程并发访问,用户可以手动同步,也可使用 Vector 替代。
LinkedList: 双向链表
线程不同步。
双向链接实现。LinkedList 同时实现了 List 接口和 Deque 接口,也就是说它既可以看作一个顺序容器,又可以看作一个队列(Queue),同时又可以看作一个栈(Stack)。
当你需要使用栈或者队列时,可以考虑使用 LinkedList,一方面是因为 Java 官方已经声明不建议使用 Stack 类,更遗憾的是,Java 里根本没有一个叫做 Queue 的类(它是个接口名字)。关于栈或队列,现在的首选是 ArrayDeque,它有着比 LinkedList(当作栈或队列使用时)有着更好的性能
Vector:实现同步的可扩容动态数组
线程同步。它的同步是通过 Iterator 方法加 synchronized 实现的。
默认初始容量为 10,当数组大小不足时容量扩大为 2 倍。
2.3 区别与联系
ArrayList底层是数组,可以通过下标直接定位到某个元素,时间复杂度为O(1),所以ArrayList更擅长read。当write的时候,如果是数组中间插入或者删除某个元素,那么则需要移动大量的元素。当我们只是read数据,或者是在末尾插入或者删除数据时,建议用ArrayList
LinkedList底层是双向链表,当我们需要read某个元素时,可以从头或者从尾部开始遍历,具体取决于离头部近还是离尾部近。当需要wirte数据时,只用移动指针。所以,LinkedList更适合存储那些常常被修改的数据。