zoukankan      html  css  js  c++  java
  • Guava BiMap AbstractBiMap

    BiMap

    BiMap是一个结构,他定义了一个Map结构,代表这个Map的key和value都具有唯一性, 并且可以生成相互联系的反向视图, 反向视图的数据会随着本体BiMap的变更而变更

    /*
     * 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

    AbstractBiMap实现了BiMap接口, 把BiMap的方法实现了一遍. 其中最主要的原理是使用forward和backward来表示两个kv相互对调的Map来构造AbstractBiMap,然后AbstractBiMap内部用

        private transient Map<K, V> delegate;
        transient AbstractBiMap<V, K> inverse;

    delegate表示的正向的Map, inverse表示的反向Map, 他们的关系就像是一个相互死循环,代码分析如下

    /*
     * 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;
    }
  • 相关阅读:
    黑马程序员__OC三大特性
    黑马程序员___OC类和对象
    黑马程序员___预处理指令
    黑马程序员___数据类型总结
    黑马程序员__指针
    黑马程序员__C语言__函数__static和extern
    黑马程序员__C语言__流程控制__选择结构
    黑马程序员__C语言__循环结构
    入园随笔
    Fiddler中抓取不到Jmeter模拟的请求包。
  • 原文地址:https://www.cnblogs.com/zemliu/p/3339412.html
Copyright © 2011-2022 走看看