BiMap是一個結構,他定義了一個Map結構,表明這個Map的key和value都具備惟一性, 而且能夠生成相互聯繫的反向視圖, 反向視圖的數據會隨着本體BiMap的變動而變動java
/* * Copyright (C) 2007 The Guava Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.common.collect; import com.google.common.annotations.GwtCompatible; import java.util.Map; import java.util.Set; import javax.annotation.Nullable; /** * A bimap (or "bidirectional map") is a map that preserves the uniqueness of * its values as well as that of its keys. This constraint enables bimaps to * support an "inverse view", which is another bimap containing the same entries * as this bimap but with reversed keys and values. * * bimap (或者叫作 "bidirectional map") 是指一個map同時保證了values和keys的惟一性. * 這種約束容許bimap支持逆視圖, 也就是另外一個bimap和它擁有相同的entry, 可是這些entry的value和key對換 * * <p>See the Guava User Guide article on <a href= * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap"> * {@code BiMap}</a>. * * @author Kevin Bourrillion * @since 2.0 (imported from Google Collections Library) */ @GwtCompatible public interface BiMap<K, V> extends Map<K, V> { // Modification Operations /** * {@inheritDoc} * * @throws IllegalArgumentException if the given value is already bound to a * different key in this bimap. The bimap will remain unmodified in this * event. To avoid this exception, call {@link #forcePut} instead. * * 若是給定的value已經存在不一樣的key中則會拋出IllegalArgumentException.在這種狀況下 * bimap會保持不變你能夠調用 forcePut 來避免這個exception */ @Override V put(@Nullable K key, @Nullable V value); /** * An alternate form of {@code put} that silently removes any existing entry * with the value {@code value} before proceeding with the {@link #put} * operation. If the bimap previously contained the provided key-value * mapping, this method has no effect. * * put 的替代方法, 在put以前他會強制移除和你想插入的value同樣的entry.若是bimap已經包含了提供的 * key-value映射, 那麼這個方法無效. * * <p>Note that a successful call to this method could cause the size of the * bimap to increase by one, stay the same, or even decrease by one. * * 注意對這個方法成功的調用會致使一個bimap的size +1, 不變, 甚至-1 (當bimap裏存在(k1, v1) * (k2, v2))而你打算forcePut(k1, v2),那麼 (k1, v1) (k2, v2) 都會被刪除 * * <p><b>Warning:</b> If an existing entry with this value is removed, the key * for that entry is discarded and not returned. * * 警告: 加入一個指定value已經存在的entry被刪除,那麼這個entry的key會被丟棄且不會被返回 * * @param key the key with which the specified value is to be associated * @param value the value to be associated with the specified key * @return the value which was previously associated with the key, which may * be {@code null}, or {@code null} if there was no previous entry * * 返回原來和這個key關聯的value, 若是原來這個key對應的entry不存在則返回null */ V forcePut(@Nullable K key, @Nullable V value); // Bulk Operations // 擴容操做 /** * {@inheritDoc} * * <p><b>Warning:</b> the results of calling this method may vary depending on * the iteration order of {@code map}. * * 警告: 這個方法的調用結果可能很是依賴於map的遍歷順序 * * @throws IllegalArgumentException if an attempt to {@code put} any * entry fails. Note that some map entries may have been added to the * bimap before the exception was thrown. * 任何put操做失敗都會拋出一個IllegalArgumentException. 注意有些map entry可能 * 在異常拋出以前已經被加到bimap裏了 */ @Override void putAll(Map<? extends K, ? extends V> map); // Views /** * {@inheritDoc} * * <p>Because a bimap has unique values, this method returns a {@link Set}, * instead of the {@link java.util.Collection} specified in the {@link Map} * interface. * * 因爲一個bimap的value具備惟一性,這個方法返回一個set而不是返回一個由map接口指定的collection */ @Override Set<V> values(); /** * Returns the inverse view of this bimap, which maps each of this bimap's * values to its associated key. The two bimaps are backed by the same data; * any changes to one will appear in the other. * * 返回一個bimap的反序視圖 -- 一個將原來的bimap的value映射到key的map, 這兩個bimaps有相同 * 的數據組成. 任何對其中一個的修改將會致使另外一個的修改 * * <p><b>Note:</b>There is no guaranteed correspondence between the iteration * order of a bimap and that of its inverse. * *提示: bimap的和它的反序視圖之間的遍歷順序是沒有保證的 * * @return the inverse view of this bimap * 返回bimap的反序視圖 */ BiMap<V, K> inverse(); }
AbstractBiMap實現了BiMap接口, 把BiMap的方法實現了一遍. 其中最主要的原理是使用forward和backward來表示兩個kv相互對調的Map來構造AbstractBiMap,而後AbstractBiMap內部用express
private transient Map<K, V> delegate; transient AbstractBiMap<V, K> inverse;
delegate表示的正向的Map, inverse表示的反向Map, 他們的關係就像是一個相互死循環,代碼分析以下apache
/* * Copyright (C) 2007 The Guava Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.common.collect; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; import com.google.common.annotations.GwtCompatible; import com.google.common.annotations.GwtIncompatible; import com.google.common.base.Objects; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.Set; import javax.annotation.Nullable; /** * A general-purpose bimap implementation using any two backing {@code Map} * instances. * * 一個由任意兩個Map實例支持的通用bimap * * <p>Note that this class contains {@code equals()} calls that keep it from * supporting {@code IdentityHashMap} backing maps. * * @author Kevin Bourrillion * @author Mike Bostock */ @GwtCompatible(emulated = true) abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V> implements BiMap<K, V>, Serializable { private transient Map<K, V> delegate; transient AbstractBiMap<V, K> inverse; /** Package-private constructor for creating a map-backed bimap. */ /** 用來建立一個map-backed的bimap包私有構造器 */ AbstractBiMap(Map<K, V> forward, Map<V, K> backward) { setDelegates(forward, backward); } /** Private constructor for inverse bimap. */ /** 用來生成bimap反向視圖的私有構造器 */ private AbstractBiMap(Map<K, V> backward, AbstractBiMap<V, K> forward) { delegate = backward; inverse = forward; } @Override protected Map<K, V> delegate() { return delegate; } /** * Returns its input, or throws an exception if this is not a valid key. * 返回輸入參數,若是key不合法則拋出一個異常 */ K checkKey(@Nullable K key) { return key; } /** * Returns its input, or throws an exception if this is not a valid value. * 返回輸入參數,若是value不合法則拋出一個異常 */ V checkValue(@Nullable V value) { return value; } /** * Specifies the delegate maps going in each direction. Called by the * constructor and by subclasses during deserialization. * * 指定各個方向的代理map. 由構造器和子類在反序列化時調用 */ void setDelegates(Map<K, V> forward, Map<V, K> backward) { checkState(delegate == null); checkState(inverse == null); checkArgument(forward.isEmpty()); checkArgument(backward.isEmpty()); checkArgument(forward != backward); delegate = forward; inverse = new Inverse<V, K>(backward, this); } void setInverse(AbstractBiMap<V, K> inverse) { this.inverse = inverse; } // Query Operations (optimizations) // 查詢操做(優化) @Override public boolean containsValue(Object value) { return inverse.containsKey(value); } // Modification Operations // 修改操做 @Override public V put(K key, V value) { return putInBothMaps(key, value, false); } @Override public V forcePut(K key, V value) { return putInBothMaps(key, value, true); } /** * 同時在delegate和inverse中插入key和value * * @param key * @param value * @param force * @return */ private V putInBothMaps(@Nullable K key, @Nullable V value, boolean force) { checkKey(key); checkValue(value); boolean containedKey = containsKey(key); // entry 已存在,直接返回value if (containedKey && Objects.equal(value, get(key))) { return value; } if (force) { // 強制put key & value inverse().remove(value); } else { // 不然檢查value是否存在,存在則拋出異常 checkArgument(!containsValue(value), "value already present: %s", value); } V oldValue = delegate.put(key, value); // 更新反向視圖 updateInverseMap(key, containedKey, oldValue, value); return oldValue; } /** * 更新反向視圖 */ private void updateInverseMap( K key, boolean containedKey, V oldValue, V newValue) { // key存在(相對於inverse來講應該是value存在),先刪除舊的entry if (containedKey) { removeFromInverseMap(oldValue); } inverse.delegate.put(newValue, key); } @Override public V remove(Object key) { return containsKey(key) ? removeFromBothMaps(key) : null; } private V removeFromBothMaps(Object key) { V oldValue = delegate.remove(key); removeFromInverseMap(oldValue); return oldValue; } private void removeFromInverseMap(V oldValue) { inverse.delegate.remove(oldValue); } // Bulk Operations // 擴容操做 @Override public void putAll(Map<? extends K, ? extends V> map) { for (Entry<? extends K, ? extends V> entry : map.entrySet()) { put(entry.getKey(), entry.getValue()); } } @Override public void clear() { delegate.clear(); inverse.delegate.clear(); } // Views // 視圖 @Override public BiMap<V, K> inverse() { return inverse; } private transient Set<K> keySet; @Override public Set<K> keySet() { Set<K> result = keySet; return (result == null) ? keySet = new KeySet() : result; } private class KeySet extends ForwardingSet<K> { @Override protected Set<K> delegate() { return delegate.keySet(); } @Override public void clear() { AbstractBiMap.this.clear(); } @Override public boolean remove(Object key) { if (!contains(key)) { return false; } removeFromBothMaps(key); return true; } @Override public boolean removeAll(Collection<?> keysToRemove) { return standardRemoveAll(keysToRemove); } @Override public boolean retainAll(Collection<?> keysToRetain) { return standardRetainAll(keysToRetain); } @Override public Iterator<K> iterator() { return Maps.keyIterator(entrySet().iterator()); } } private transient Set<V> valueSet; @Override public Set<V> values() { /* * We can almost reuse the inverse's keySet, except we have to fix the * iteration order so that it is consistent with the forward map. * * 咱們能夠重用inverse的keyset來獲得forward的valueset, 除非咱們關注遍歷器的順序, * 那樣能夠考慮使用forward map */ Set<V> result = valueSet; return (result == null) ? valueSet = new ValueSet() : result; } private class ValueSet extends ForwardingSet<V> { /** 使用inverse的keySet來獲取valueSet */ final Set<V> valuesDelegate = inverse.keySet(); @Override protected Set<V> delegate() { return valuesDelegate; } @Override public Iterator<V> iterator() { return Maps.valueIterator(entrySet().iterator()); } @Override public Object[] toArray() { return standardToArray(); } @Override public <T> T[] toArray(T[] array) { return standardToArray(array); } @Override public String toString() { return standardToString(); } } private transient Set<Entry<K, V>> entrySet; @Override public Set<Entry<K, V>> entrySet() { Set<Entry<K, V>> result = entrySet; return (result == null) ? entrySet = new EntrySet() : result; } private class EntrySet extends ForwardingSet<Entry<K, V>> { final Set<Entry<K, V>> esDelegate = delegate.entrySet(); @Override protected Set<Entry<K, V>> delegate() { return esDelegate; } @Override public void clear() { AbstractBiMap.this.clear(); } @Override public boolean remove(Object object) { if (!esDelegate.contains(object)) { return false; } // safe because esDelgate.contains(object). Entry<?, ?> entry = (Entry<?, ?>) object; inverse.delegate.remove(entry.getValue()); /* * Remove the mapping in inverse before removing from esDelegate because * if entry is part of esDelegate, entry might be invalidated after the * mapping is removed from esDelegate. * * 刪除forward的entry以前先將inverse的entry刪除,由於若是entry是forward的一部分, * 那麼entry可能會在forward中刪除之後變成不可用 */ esDelegate.remove(entry); return true; } @Override public Iterator<Entry<K, V>> iterator() { final Iterator<Entry<K, V>> iterator = esDelegate.iterator(); return new Iterator<Entry<K, V>>() { Entry<K, V> entry; @Override public boolean hasNext() { return iterator.hasNext(); } @Override public Entry<K, V> next() { entry = iterator.next(); final Entry<K, V> finalEntry = entry; return new ForwardingMapEntry<K, V>() { @Override protected Entry<K, V> delegate() { return finalEntry; } @Override public V setValue(V value) { // Preconditions keep the map and inverse consistent. checkState(contains(this), "entry no longer in map"); // similar to putInBothMaps, but set via entry if (Objects.equal(value, getValue())) { return value; } checkArgument(!containsValue(value), "value already present: %s", value); V oldValue = finalEntry.setValue(value); checkState(Objects.equal(value, get(getKey())), "entry no longer in map"); updateInverseMap(getKey(), true, oldValue, value); return oldValue; } }; } @Override public void remove() { checkState(entry != null); V value = entry.getValue(); iterator.remove(); removeFromInverseMap(value); } }; } // See java.util.Collections.CheckedEntrySet for details on attacks. @Override public Object[] toArray() { return standardToArray(); } @Override public <T> T[] toArray(T[] array) { return standardToArray(array); } @Override public boolean contains(Object o) { return Maps.containsEntryImpl(delegate(), o); } @Override public boolean containsAll(Collection<?> c) { return standardContainsAll(c); } @Override public boolean removeAll(Collection<?> c) { return standardRemoveAll(c); } @Override public boolean retainAll(Collection<?> c) { return standardRetainAll(c); } } /** The inverse of any other {@code AbstractBiMap} subclass. */ /** inverse類, 實際上實現很簡單,就是把AbstractBiMap的forward和inverse給反過來了 */ private static class Inverse<K, V> extends AbstractBiMap<K, V> { private Inverse(Map<K, V> backward, AbstractBiMap<V, K> forward) { super(backward, forward); } /* * Serialization stores the forward bimap, the inverse of this inverse. * Deserialization calls inverse() on the forward bimap and returns that * inverse. * * 序列化儲存forward bimap, inverse的反向. * 反序列化調用forward的inverse()並返回這個inverse * * If a bimap and its inverse are serialized together, the deserialized * instances have inverse() methods that return the other. */ @Override K checkKey(K key) { return inverse.checkValue(key); } @Override V checkValue(V value) { return inverse.checkKey(value); } /** * @serialData the forward bimap * * 因爲 delegate和inverse都有transient關鍵字 * 因此序列化方法只會序列化inverse()的內容 */ @GwtIncompatible("java.io.ObjectOuputStream") private void writeObject(ObjectOutputStream stream) throws IOException { stream.defaultWriteObject(); stream.writeObject(inverse()); } /** * 反序列化恢復inverse */ @GwtIncompatible("java.io.ObjectInputStream") @SuppressWarnings("unchecked") // reading data stored by writeObject private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); setInverse((AbstractBiMap<V, K>) stream.readObject()); } /** * 最後反序列化返回的是inverse().inverse(),其實就是forward了. */ @GwtIncompatible("Not needed in the emulated source.") Object readResolve() { return inverse().inverse(); } @GwtIncompatible("Not needed in emulated source.") private static final long serialVersionUID = 0; } @GwtIncompatible("Not needed in emulated source.") private static final long serialVersionUID = 0; }