首先我们来看一下基本的java集合框架图!
由上图我们通过前面的博客了解到集合是个什么东西,接下来,在我看来集合其实可以分为两个部分的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。Collection 接口又有 3 种子类型,List、Set 和 Queue,再下面是一些抽象类,最后是具体实现类,常用的有 ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap 等等。
对于所有集合来说我们都需要了解一个东西,就是Iterator(迭代器),它对于我们来说就是一个工具,让我们可以更加自由的去迭代或者删除其中的元素,因为有时由于数据类型的原因,增加或删除的方式大大不同,所以迭代器就出现了。
boolean hasnext(): 如果被迭代的元素还没有遍历完,则返回true。
Object next(): 返回集合中的下一个元素。
void remove():删除集合集合中上一次next方法返回的元素。
这三个方法为迭代器的最基本的方法,不论任何集合的迭代器都存在这三个方法,而它的一个子接口 ListIterator 在它的基础上又添加了三种方法,分别是 add(),previous(),hasPrevious()。也就是说如果实现 Iterator 接口,那么在遍历集合中元素的时候,只能往后遍历,被遍历后的元素不会再被遍历到,通常无序集合实现的都是这个接口,比如HashSet;而那些元素有序的集合,实现的一般都是 LinkedIterator接口,实现这个接口的集合可以双向遍历,既可以通过next()访问下一个元素,又可以通过previous()访问前一个 元素,比如ArrayList。
今天我们主讲一下collection这个我称之为基本集合类的相关内容。
首先是List接口
List接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素。
List 接口存储一组不唯一,有序(插入顺序)的对象。
实现类有ArrayList、LinkedList、Vector、Stack等
ArrayList是基于数组实现的,是一个数组队列。可以动态的增加容量!
LinkedList是基于链表实现的,是一个双向循环列表。可以被当做堆栈使用!
Vector是基于数组实现的,是一个矢量队列,是线程安全的!
Stack是基于数组实现的,是栈,它继承与Vector,特性是FILO(先进后出)!
其中对于List我认为最重要的就是ArrayList和LinkedList这两者的区别了
1. 当集合中对插入元素数据的速度要求不高,但是要求快速访问元素数据,则使用ArrayList!
2. 当集合中对访问元素数据速度不做要求不高,但是对插入和删除元素数据速度要求高的情况,则使用LinkedList!
为什么ArrayList读取速度快于LinkedList,而插入和删除速度又慢于LinkedList?
ArrayList随机读取的时候采用的是get(index),根据指定位置读取元素,而LinkedList则采用size/2 ,二分法去加速一次读取元素!
LinkedList:
Node<E> node(int index) {
// assert isElementIndex(index);
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
ArrayList
public E get(int index) {
rangeCheck(index);
return elementData(index); //直接通过数组下标来得到数据
}
ArrayList插入时候要判断容量,删除时候要将数组移位,有一个复制操作!而LinkedList直接插入,不用判断容量,删除的时候也是直接删除跳转指针节点,没有复制的操作!
ArrayList
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!判断是否需要扩容
elementData[size++] = e;
return true;
}
LinkedList
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++;
}