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长度是固定的,不能扩容。