ImmutableCollections即不可变即,最初出现在Google 的Guava 中,在jdk的Java9中被引入。

JDK9,10中的ImmutableCollections只是一个存放不可变集合的一个容器,不是一个公共的API。

先看ImmutableCollections的设计图

ImmutableCollections真的只是一个集合,下面的Set0,Set1..List1,ListN才是运用的对象。

注意:ImmutableCollections定义并非public class,则它只能被同个包下面的对象访问。并且这些访问往往有很多限制。

在这里我并不会讲所有的,只讲一个Map类型的,其它类型的道理是一样的。

    static final class Map0<K,V> extends AbstractImmutableMap<K,V> {
        private static final Map0<?,?> INSTANCE = new Map0<>();

        @SuppressWarnings("unchecked")
        static <K,V> Map0<K,V> instance() {
            return (Map0<K,V>) INSTANCE;
        }

        private Map0() { }

        @Override
        public Set<Map.Entry<K,V>> entrySet() {
            return Set.of();
        }

        @Override
        public boolean containsKey(Object o) {
            Objects.requireNonNull(o);
            return false;
        }

        @Override
        public boolean containsValue(Object o) {
            Objects.requireNonNull(o);
            return false;
        }

        //这个方法表示取消序列化
        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
            throw new InvalidObjectException("not serial proxy");
        }

        //这个方法表示取消序列化
        private Object writeReplace() {
            return new CollSer(CollSer.IMM_MAP);
        }

        @Override
        public int hashCode() {
            return 0;
        }
    }

注意:这个方法是static,并且使用了static变量,则这个方法是非线程安全的,又使用了单例模式的private掉无参构造函数,则只能是返回的都是同一个对象。

    static final class Map1<K,V> extends AbstractImmutableMap<K,V> {
        @Stable
        private final K k0;
        @Stable
        private final V v0;

        Map1(K k0, V v0) {
            this.k0 = Objects.requireNonNull(k0);
            this.v0 = Objects.requireNonNull(v0);
        }

        @Override
        public Set<Map.Entry<K,V>> entrySet() {
            return Set.of(new KeyValueHolder<>(k0, v0));
        }

        @Override
        public boolean containsKey(Object o) {
            return o.equals(k0); // implicit nullcheck of o
        }

        @Override
        public boolean containsValue(Object o) {
            return o.equals(v0); // implicit nullcheck of o
        }

        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
            throw new InvalidObjectException("not serial proxy");
        }

        private Object writeReplace() {
            return new CollSer(CollSer.IMM_MAP, k0, v0);
        }

        @Override
        public int hashCode() {
            return k0.hashCode() ^ v0.hashCode();
        }
    }

这个方法主要是给定一个key-value,然后自己返回一个Map。

    static final class MapN<K,V> extends AbstractImmutableMap<K,V> {
        @Stable
        final Object[] table; // pairs of key, value
        @Stable
        final int size; // number of pairs

        MapN(Object... input) {
            if ((input.length & 1) != 0) { // implicit nullcheck of input
                throw new InternalError("length is odd");
            }
            size = input.length >> 1;

            int len = EXPAND_FACTOR * input.length;
            len = (len + 1) & ~1; // ensure table is even length
            table = new Object[len];

            for (int i = 0; i < input.length; i += 2) {
                @SuppressWarnings("unchecked")
                    K k = Objects.requireNonNull((K)input[i]);
                @SuppressWarnings("unchecked")
                    V v = Objects.requireNonNull((V)input[i+1]);
                int idx = probe(k);
                if (idx >= 0) {
                    throw new IllegalArgumentException("duplicate key: " + k);
                } else {
                    int dest = -(idx + 1);
                    table[dest] = k;
                    table[dest+1] = v;
                }
            }
        }
        ....
    }

其实那个final Object table[]其实就是Map对象了,但是在这里实现一个这个,看看使用着只是Interface Map的of。of可以算是Java9之后新添加的一个概念,更加方便初始化。但是这里的table长度是固定的,不能扩容。


本文转载:CSDN博客