一、前言
今天開始閱讀jdk1.8的集合部分,平時在寫項目的時候,用到的最多的部分可能就是Java的集合框架,通過閱讀集合框架源碼,了解其內部的數據結構實現,能夠深入理解各個集合的性能特性,並且能夠幫助自己在今后的開發中避免犯一些使用錯誤。另外筆者自己也是摸着石頭過河,如果有描述不當的地方,希望園友們能夠不吝指出,希望能夠和大家共同進步!
二、集合框架概覽圖

可以看到集合的基礎接口是Map, Collection以及Iterator。其余的類都實現自這3個類。
- 藍色為接口,紅色為類,綠色為抽象類。
- 空心三角形虛線:實現接口(implements),好像也不太准確,列如list和collection的關系是extends。因為list是接口
- 空心三角形實線:繼承(extends)
三、基礎接口的源碼解析
3.1 Iterator接口
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
/**
* 舉個簡單例子(把集合里的元素每個都輸出出來):
* List<String> names = new ArrayList<>();
* names.add("Joemsu");
* names.add("GodnessY");
* names.iterator().forEachRemaining(c -> System.out.println("hi! " + c));
*/
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
可以看到Iterator接口還是很簡單的,做到了見名知意,值得一提的是里面的remove方法:此方法可用於在迭代中刪除結合中的元素,如果不用Iterator,在list循環中使用remove會拋異常。另外forEachRemaining()給出了簡單的例子,里面的Consumer函數式接口有空再具體講解。
3.2 Collection接口
public interface Collection<E> extends Iterable<E> {
//值得一提的是:如果size超過Integer.MAX_VALUE也只會返回Integer.MAX_VALUE
int size();
boolean isEmpty();
//如果向集合里添加null,使用contains(null),也可以返回true
boolean contains(Object o);
Iterator<E> iterator();
/**
* 深層拷貝,修改數組的數據不會對集合里的元素產生影響。
* 注意:只能返回Object[],不能強制轉換其他類型,如需要轉型,使用下面帶泛型的方法。
*/
Object[] toArray();
<T> T[] toArray(T[] a);
boolean add(E e);
boolean remove(Object o);
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
boolean removeAll(Collection<?> c);
//保留c集合里的元素
boolean retainAll(Collection<?> c);
void clear();
boolean equals(Object o);
//如過a.equals(b),則hashCode()肯定相同,反之不一定
int hashCode();
//針對parallelStream()添加的方法,用於分割集合,進行並行處理
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, 0);
}
/**
* 如果滿足filter,則刪除,舉個栗子:
* Collection<String> myHeart = new ArrayList<>();
* myHeart.add("Boduolaoshi");
* myHeart.add("GodnessY");
* System.out.println("before: " + myHeart.size());
* myHeart.removeIf(s -> s.equals("Boduolaoshi"));
* System.out.println("after: " + myHeart.size());
*/
default boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
//采用並行處理,使用多核cpu的特性
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
}
需要注意的一些地方已經在注釋這里特別說明過了,另外對於spliterator(),不是特別清楚的園友們,可以點擊查看這里,回答的已經很詳細了。
3.3 Map接口
public interface Map<K,V> {
//同樣的,如果size超過Integer.MAX_VALUE也只會返回Integer.MAX_VALUE
int size();
boolean isEmpty();
boolean containsKey(Object key);
boolean containsValue(Object value);
V get(Object key);
V put(K key, V value);
V remove(Object key);
void putAll(Map<? extends K, ? extends V> m);
void clear();
//對set的變動會影響到map,反過來也一樣
Set<K> keySet();
//對Collection的變動會影響到map,反過來也一樣
Collection<V> values();
//對Set的變動會影響到map,反過來也一樣
Set<Map.Entry<K, V>> entrySet();
boolean equals(Object o);
int hashCode();
//Entry start
interface Entry<K,V> {
K getKey();
V getValue();
V setValue(V value);
boolean equals(Object o);
int hashCode();
//使用默認方法對Key進行比較
public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> comparingByKey(){
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> c1.getKey().compareTo(c2.getKey());
}
//使用默認方法對Value比較
public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> comparingByValue() {
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> c1.getValue().compareTo(c2.getValue());
}
/**
* 自己傳比較的方法,舉個栗子:
* Map<String, Integer> map = new HashMap<>();
* map.put("sorted", 2);
* map.put("collect", 1);
* map.put("each", 3);
* System.out.println("before sort");
* map.entrySet().forEach(System.out::println);
* System.out.println("after sort");
* map.entrySet()
* .stream()
* .sorted(Map.Entry.comparingByKey((a, b) -> a.length() - b.length()))
* .collect(Collectors.toList()).forEach(System.out::println);
*/
public static <K, V> Comparator<Map.Entry<K, V>> comparingByKey(Comparator<? super K> cmp) {
Objects.requireNonNull(cmp);
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> cmp.compare(c1.getKey(), c2.getKey());
}
public static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V> cmp) {
Objects.requireNonNull(cmp);
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> cmp.compare(c1.getValue(), c2.getValue());
}
}
//Entry end
//獲取指定key 的value,沒有則返回默認值
default V getOrDefault(Object key, V defaultValue) {
V v;
return (((v = get(key)) != null) || containsKey(key))
? v
: defaultValue;
}
/**
* 對每隊鍵值對操作: map.forEach((i, j) -> System.out.println(i + j))
* 注意這里的(i, j)的類型與你初始化map的鍵值類型對應,i即K, j即V
*/
default void forEach(BiConsumer<? super K, ? super V> action) {
Objects.requireNonNull(action);
for (Map.Entry<K, V> entry : entrySet()) {
K k;
V v;
try {
k = entry.getKey();
v = entry.getValue();
} catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
}
action.accept(k, v);
}
}
/**
* 傳入BiFunction類型,對每個鍵值對進行處理,返回類型與V類型相同
* Map<String, Integer> map = new HashMap<>();
* map.put("hi", 3);
* map.put("hello", 4);
* BiFunction<String, Integer, Integer> bi = (a, b) -> a.length() + b; //為了容易理解,這么寫
* map.forEach((i, j) -> System.out.println(i + ":" + j));
* map.replaceAll(bi);
* map.forEach((i, j) -> System.out.println(i + ":" + j));
*/
default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
Objects.requireNonNull(function);
for (Map.Entry<K, V> entry : entrySet()) {
K k;
V v;
try {
k = entry.getKey();
v = entry.getValue();
} catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
}
// ise thrown from function is not a cme.
v = function.apply(k, v);
try {
entry.setValue(v);
} catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
}
}
}
//如果為空的話,插入
default V putIfAbsent(K key, V value) {
V v = get(key);
if (v == null) {
v = put(key, value);
}
return v;
}
default boolean remove(Object key, Object value) {
Object curValue = get(key);
if (!Objects.equals(curValue, value) ||
(curValue == null && !containsKey(key))) {
return false;
}
remove(key);
return true;
}
default boolean replace(K key, V oldValue, V newValue) {
Object curValue = get(key);
if (!Objects.equals(curValue, oldValue) ||
(curValue == null && !containsKey(key))) {
return false;
}
put(key, newValue);
return true;
}
default V replace(K key, V value) {
V curValue;
if (((curValue = get(key)) != null) || containsKey(key)) {
curValue = put(key, value);
}
return curValue;
}
//如果key不存在,則通過mappingFunction生成value,並插入
default V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
Objects.requireNonNull(mappingFunction);
V v;
if ((v = get(key)) == null) {
V newValue;
if ((newValue = mappingFunction.apply(key)) != null) {
put(key, newValue);
return newValue;
}
}
return v;
}
//如果存在key對應的值,則通過remappingFunction來計算新的value,(value不為空)然后更新,為空則刪除key
default V computeIfPresent(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
V oldValue;
if ((oldValue = get(key)) != null) {
V newValue = remappingFunction.apply(key, oldValue);
if (newValue != null) {
put(key, newValue);
return newValue;
} else {
remove(key);
return null;
}
} else {
return null;
}
}
default V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
V oldValue = get(key);
V newValue = remappingFunction.apply(key, oldValue);
if (newValue == null) {
// delete mapping
if (oldValue != null || containsKey(key)) {
// something to remove
remove(key);
return null;
} else {
// nothing to do. Leave things as they were.
return null;
}
} else {
// add or replace old mapping
put(key, newValue);
return newValue;
}
}
//將舊的oldValue和新的傳進去value通過remappingFunction進行處理,然后更新
default V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
Objects.requireNonNull(value);
V oldValue = get(key);
V newValue = (oldValue == null) ? value :
remappingFunction.apply(oldValue, value);
if(newValue == null) {
remove(key);
} else {
put(key, newValue);
}
return newValue;
}
}
那么Map的接口源碼閱讀就到這里。
四、總結
總的來說,jdk1.8集合與之前版本不同的地方就是加入了很多default方法,以及使用了各種函數型接口,但總體來說還是比較好理解的。后面會更新其他的實現類,謝謝各位園友觀看,如果有描述不對的地方歡迎指正。