Guava源码分析——Immutable Collections(4)
Immutable的集合體系,還有中很重要的集合沒有介紹,就是ImmutableMap,通過UML圖,可以看出ImmutableMap的結(jié)構(gòu)體系。
首先來看一下ImmutableBiMap,因為普通ImmutableMap的實現(xiàn)依賴于它。ImmutableBiMap在ImmutableMap的基礎(chǔ)上,加入inverse()等方法,可以使鍵值反轉(zhuǎn)。ImmutableBiMap的構(gòu)造,也是根據(jù)元素個數(shù)的不同,使用不同的實現(xiàn)(0-->EmptyImmutablBiMap,1-->SingletonImmutablBiMap,n(n>=2)-->RegularImmubtalMap),代碼如下所示:
public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V> implements BiMap<K, V> {public static <K, V> ImmutableBiMap<K, V> of() {//Empty元素內(nèi)部,不維護(hù)存儲結(jié)構(gòu),inverse()方法直接返回thisreturn (ImmutableBiMap<K, V>) EmptyImmutableBiMap.INSTANCE;}public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1) {//單個元素構(gòu)造時,返回此類,內(nèi)部維護(hù)兩個元素K,V,inverse()時,返回V,K的SingletonImmutableBiMapreturn new SingletonImmutableBiMap<K, V>(k1, v1);}public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2) {//多個元素構(gòu)造是,返回此類,內(nèi)部維護(hù)兩個Entry[]集合,一個以key作為hashbucket的位置,//另一個以value作為hashbucket的位置,用于inverse()的時候,key-value的反轉(zhuǎn)return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2));} }
copyOf()方法,在ImmutableCollections中實現(xiàn)的原則就是,如果copyOf()的還是一份ImmutableCollections集合,那么只是進(jìn)行引用的賦值,因為集合本身不可變。
看過ImmutableBiMap之后,在回頭看ImmutableMap就簡單了很多,只是在ImmutableBiMap基礎(chǔ)上去除了inverse()方法,并在內(nèi)部為戶單一數(shù)組(hashbucket)
不需要維護(hù)反轉(zhuǎn)的數(shù)組。在無元素和單一元素構(gòu)造的時候,直接調(diào)用ImmutableBiMap.of()和ImmutableBiMap.of(K,V)方法,代碼如下所示:
public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {/*** Returns the empty map. This map behaves and performs comparably to* {@link Collections#emptyMap}, and is preferable mainly for consistency* and maintainability of your code.*/public static <K, V> ImmutableMap<K, V> of() {return ImmutableBiMap.of();}/*** Returns an immutable map containing a single entry. This map behaves and* performs comparably to {@link Collections#singletonMap} but will not accept* a null key or value. It is preferable mainly for consistency and* maintainability of your code.*/public static <K, V> ImmutableMap<K, V> of(K k1, V v1) {return ImmutableBiMap.of(k1, v1);} }多個元素構(gòu)造的時候,返回RegularImmubtalMap,與RegularImmutableBiMap內(nèi)部實現(xiàn)大同小異,去除對反轉(zhuǎn)(值-鍵)的數(shù)組維護(hù),去除inverse()等方法。
最后簡單的闡述一下ImmutableSortedMap的實現(xiàn),ImmutableMap單一元素和空元素的實現(xiàn),就不詳細(xì)說了,有興趣的讀者可以自己看看。多元素實現(xiàn)的時候,
ImmutableSortedMap的具體實現(xiàn)類是RegularImmutableSortedMap,有意思的是,它的內(nèi)部維護(hù)key和value的數(shù)據(jù)結(jié)構(gòu)是兩個List,那么可想而知,排序早在構(gòu)造的時候就已經(jīng)完成了,而事實確實是這樣,具體代碼如下所示:
@SuppressWarnings("unchecked")public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {//將排序器和entires傳入fromEntries方法return fromEntries(Ordering.natural(), false, 4, entryOf(k1, v1), entryOf(k2, v2),entryOf(k3, v3), entryOf(k4, v4));} static <K, V> ImmutableSortedMap<K, V> fromEntries(Comparator<? super K> comparator, boolean sameComparator, int size, Entry<K, V>... entries) {for (int i = 0; i < size; i++) {Entry<K, V> entry = entries[i];entries[i] = entryOf(entry.getKey(), entry.getValue());}if (!sameComparator) {sortEntries(comparator, size, entries);//遍歷entries排序 validateEntries(size, entries, comparator);}return fromSortedEntries(comparator, size, entries);} static <K, V> ImmutableSortedMap<K, V> fromSortedEntries( Comparator<? super K> comparator,int size,Entry<K, V>[] entries) {if (size == 0) {return emptyMap(comparator);}//遍歷排序之后的entries,分開key和value,分別組成各自的ListImmutableList.Builder<K> keyBuilder = ImmutableList.builder();ImmutableList.Builder<V> valueBuilder = ImmutableList.builder();for (int i = 0; i < size; i++) {Entry<K, V> entry = entries[i];keyBuilder.add(entry.getKey());valueBuilder.add(entry.getValue());}return new RegularImmutableSortedMap<K, V>(new RegularImmutableSortedSet<K>(keyBuilder.build(), comparator),valueBuilder.build()); }?ImmutableMap中的Entry,也是被Guava重新實現(xiàn),增加了bucket的計算邏輯,如下圖UML:
AbstractMapEntry在原有Map.entry基礎(chǔ)上,將寫操作,置為直接拋異常,ImmutableEntry實現(xiàn)getKey()和getValue(),ImmutableMapEntry再加入bucket的計算和維護(hù)方法(鏈表),最終反映到NonTerminalMapEntry和TerminalEntry,對于這兩個類,TerminalEntry為bucket鏈表的尾結(jié)點(diǎn),所以實現(xiàn)如下:
static final class TerminalEntry<K, V> extends ImmutableMapEntry<K, V> {TerminalEntry(ImmutableMapEntry<K, V> contents) {super(contents);}TerminalEntry(K key, V value) {super(key, value);}@Override@NullableImmutableMapEntry<K, V> getNextInKeyBucket() {//尾節(jié)點(diǎn),所以沒有nuextreturn null;}@Override@NullableImmutableMapEntry<K, V> getNextInValueBucket() {//尾節(jié)點(diǎn),所以沒有nuextreturn null;}}而NonTerminalMapEntry的構(gòu)造則需要傳入下一個Entry
private static final class NonTerminalMapEntry<K, V> extends ImmutableMapEntry<K, V> {private final ImmutableMapEntry<K, V> nextInKeyBucket;NonTerminalMapEntry(K key, V value, ImmutableMapEntry<K, V> nextInKeyBucket) {super(key, value);this.nextInKeyBucket = nextInKeyBucket;}NonTerminalMapEntry(ImmutableMapEntry<K, V> contents, ImmutableMapEntry<K, V> nextInKeyBucket) {super(contents);this.nextInKeyBucket = nextInKeyBucket;}@OverrideImmutableMapEntry<K, V> getNextInKeyBucket() {//同一個bucket中的下一個Entryreturn nextInKeyBucket;}@Override@NullableImmutableMapEntry<K, V> getNextInValueBucket() {//BiMap才會維護(hù)Value的Bucketreturn null;}}那么在構(gòu)造的時候,如果產(chǎn)生hash沖突,就是用nonTerminalMapEntry,代碼如下所示:
RegularImmutableMap(Entry<?, ?>[] theEntries) {int size = theEntries.length;entries = createEntryArray(size);int tableSize = Hashing.closedTableSize(size, MAX_LOAD_FACTOR);table = createEntryArray(tableSize);mask = tableSize - 1;for (int entryIndex = 0; entryIndex < size; entryIndex++) {@SuppressWarnings("unchecked") // all our callers carefully put in only Entry<K, V>sEntry<K, V> entry = (Entry<K, V>) theEntries[entryIndex];K key = entry.getKey();V value = entry.getValue();checkEntryNotNull(key, value);int tableIndex = Hashing.smear(key.hashCode()) & mask;@Nullable ImmutableMapEntry<K, V> existing = table[tableIndex];// prepend, not append, so the entries can be immutable//在構(gòu)造是,如果產(chǎn)生hash沖突,那么直接的append到terminal的前面ImmutableMapEntry<K, V> newEntry = (existing == null)? new TerminalEntry<K, V>(key, value): new NonTerminalMapEntry<K, V>(key, value, existing);table[tableIndex] = newEntry;entries[entryIndex] = newEntry;checkNoConflictInBucket(key, newEntry, existing);}}?
轉(zhuǎn)載于:https://www.cnblogs.com/pona/p/4564256.html
總結(jié)
以上是生活随笔為你收集整理的Guava源码分析——Immutable Collections(4)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 漏洞扫描工具AppScan下载网盘
- 下一篇: 下拉到底部加载更多