Java集合主要可以划分为4个部分:List列表、Set集合、Map映射、工具类(Iterator迭代器、Enumeration枚举类、Arrays和Collections)。
Collection
Collection的爸爸
Collection接口继承Iterrable接口,
Iterrable:提供迭代的功能
public interface Iterable<T> {
Iterator<T> iterator();
}
Iterator:迭代器,用于遍历一个序列类似一个游标。
public Interface Iterator{
boolean hasNext();
Object next();
void remove();
}
Collection的宝宝
看完了Collection的来历,我们再看看的延伸:
Collection
public interface Collection<E> extends Iterable<E> {}
它是一个接口,是高度抽象出来的集合,它包含了集合的基本操作:添加、删除、清空、遍历(读取)、是否为空、获取大小、是否保护某元素等等。
Collection接口包含了List和Set两大分支。
- List是一个有序的队列,每一个元素都有它的索引。第一个元素的索引值是0。
List的实现类有LinkedList, ArrayList, Vector, Stack。 - Set是一个不允许有重复元素的集合。
Set的实现类有HastSet和TreeSet。HashSet依赖于HashMap,它实际上是通过HashMap实现的;TreeSet依赖于TreeMap,它实际上是通过TreeMap实现的。
List是有序的队列,List中可以有重复的元素;
Set是数学概念中的集合,Set中没有重复元素。
List
public interface List<E> extends Collection<E> {}
List是有序的队列,List中的每一个元素都有一个索引;第一个元素的索引值是0,往后的元素的索引值依次+1。List中允许有重复的元素。
Set
public interface Set<E> extends Collection<E> {}
Set是数学概念中的集合,Set中没有重复元素。
ArrayList
ArrayList 实现了动态数组,它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口。
遍历ArrayList时,使用随机访问(即,通过索引序号访问)效率最高,而使用迭代器的效率最低。
ArrayList的Add扩容
在add时,先确认数组长度是否足够(这个过程首先检查内部数组是否为空,如果为空就设定默认的初始容量(10) ),接着判断当前需要的容量是否大于内部数组,大于的话就进行扩容。
扩容的过程是,将内部数组拷贝到一个新的大小为原数组1.5倍的数组中(这里也要先计算,来判断扩容后是否会过大,出现溢出等情况),然后将内部数组的引用改为新数组。
LinkedList
双向链表,定义了Node(Entry — 1.8之前)
LinkedList的Add扩容:
JDK1.8之前:
不得不说它的addBefore方法 addBefore(E e, Entry entry)
就是在entry结点之前插入一个新的结点存放e。
public boolean add(E e) {
addBefore(e, header);
return true;
}
public void add(int index, E element) {
addBefore(element, (index==size ? header : entry(index)));
}
public void addFirst(E e) {
addBefore(e, header.next);
}
public void addLast(E e) {
addBefore(e, header);
}
JDK1.8:
public boolean add(E e) {
// 添加到末尾
linkLast(e);
return true;
}
void linkLast(E e) {
// 保存尾结点,l为final类型,不可更改
final Node<E> l = last;
// 新生成结点的前驱为l,后继为null
final Node<E> newNode = new Node<>(l, e, null);
// 重新赋值尾结点
last = newNode;
if (l == null) // 尾结点为空
first = newNode; // 赋值头结点
else // 尾结点不为空
l.next = newNode; // 尾结点的后继为新生成的结点
// 大小加1
size++;
// 结构性修改加1
modCount++;
}
当然,它也提供了LinkFirst()插入第一个元素,LinkBefore()来插入元素等方法。