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()來插入元素等方法。