这篇文章是续着昨天的《Guava学习之SetMultimap》写的。AbstractSetMultimap是一个抽象类,主要是实现SetMultimap接口中的方法,但是其具体的实现都是调用了AbstractMapBasedMultimap类中的相应实现,只是将AbstractMapBasedMultimap类中返回类行为Collection的修改为Set。下面主要说说AbstractSetMultimap类的相关实现。
1、在AbstractMapBasedMultimap类中就说了其子类必须重写createCollection()方法,而AbstractSetMultimap类根据其子类的实现,将createCollection()方法的返回类型修改为Set了(AbstractMapBasedMultimap类中返回类型是Collection),新的函数原型如下:
@Override abstract Set<V> createCollection();
但是其具体的实现得等到子类才能确定。
2、AbstractSetMultimap类的get函数实现如下:
@Override
public Set<V> get(@Nullable K key) {
return (Set<V>) super.get(key);
}
里面很简单,调用了其父类(AbstractMapBasedMultimap)的get方法,具体实现如下:
@Override
public Collection<V> get(@Nullable K key) {
Collection<V> collection = map.get(key);
if (collection == null) {
collection = createCollection(key);
}
return wrapCollection(key, collection);
}
具体的过程:从map中找到key对应的元素复制给collection,因为用户输入的key可能在map中没有,所以collection可能为null,这样新创建一个collection用于存储key对应的value,最后将collection包装起来并返回。
3、AbstractSetMultimap类的entries函数实现如下:
@Override
public Set<Map.Entry<K, V>> entries() {
return (Set<Map.Entry<K, V>>) super.entries();
}
里面的具体实现也是调用了其父类的entries实现,其父类的entries方法的实现如下:
private transient Collection<Entry<K, V>> entries;
@Override
public Collection<Entry<K, V>> entries() {
Collection<Entry<K, V>> result = entries;
return (result == null) ? entries = createEntries() : result;
}
为了效率,其父类将元素存放在一个变量中,当用户需要这个数据时,先判断当前内存是否已经有了,如果有,则直接返回内存中的数据;如果没有,则再去生成,并将生成的数据存放在内存一份,为下一次取数据提供了方便,这样的设计设计不需要每次都生成entries,只有当内存中不存在数据才生成,对于频繁的访问entries可以大大的减少访问的时间。、
4、AbstractSetMultimap类的removeAll函数实现如下:
@Override
public Set<V> removeAll(@Nullable Object key) {
return (Set<V>) super.removeAll(key);
}
父类的removeAll函数实现
@Override
public Collection<V> removeAll(@Nullable Object key) {
Collection<V> collection = map.remove(key);
if (collection == null) {
return createUnmodifiableEmptyCollection();
}
Collection<V> output = createCollection();
output.addAll(collection);
totalSize -= collection.size();
collection.clear();
return unmodifiableCollectionSubclass(output);
}
具体的实现步骤:(1)、从map中删除掉key等于用户输入的key,并将key对应的value存入collection中;
(2)、如果map中不存在相应的key,则collection是为空的,这样只需要建立空的不可修改的collection直接返回就行;
(3)、如果collection不为空,则建立一个临时的output,并将collection中的所有元素都添加进output中。因为是删除,所以需要将map中总的value个数减去删除的value个数,并清空collection中的元素;并将output里面的元素封装成不可修改的collection,最后返回。
AbstractSetMultimap类的replaceValues函数实现如下:
@Override
public Set<V> replaceValues(
@Nullable K key, Iterable<? extends V> values) {
return (Set<V>) super.replaceValues(key, values);
}
真实实现:
@Override
public Collection<V> replaceValues(@Nullable K key,
Iterable<? extends V> values) {
Iterator<? extends V> iterator = values.iterator();
if (!iterator.hasNext()) {
return removeAll(key);
}
// TODO(user): investigate atomic failure?
Collection<V> collection = getOrCreateCollection(key);
Collection<V> oldValues = createCollection();
oldValues.addAll(collection);
totalSize -= collection.size();
collection.clear();
while (iterator.hasNext()) {
if (collection.add(iterator.next())) {
totalSize++;
}
}
return unmodifiableCollectionSubclass(oldValues);
}
private Collection<V> getOrCreateCollection(@Nullable K key) {
Collection<V> collection = map.get(key);
if (collection == null) {
collection = createCollection(key);
map.put(key, collection);
}
return collection;
}
实现步骤:(1)、如果输入的values为空,则replaceValues函数相当于removeAll函数;
(2)、getOrCreateCollection函数根据key在map中寻找相应的key的value并存储在collection中。如果collection为空,则新建一个collection用于表示key元素存储的地方,并将key和其对应value存储结构添加到map中去。最后返回key对应的value存储结构。从getOrCreateCollection实现可以看出,如果map中不存在对应的key值,则replaceValues函数相当于putAll(K key, Iterable< ? extends V> values)函数,也就是将key和其对应的values添加到map中。
(3)、将getOrCreateCollection函数返回的collection中的数据全部添加到oldValues中去,并清空collection里面的元素,从totalSize减去被清空的值的个数。
(4)、将values中的元素全部作为key的值并添加到map中去。最后返回本次添加的values的不可变集合。
AbstractSetMultimap类的put函数实现如下:
@Override
public boolean put(@Nullable K key, @Nullable V value) {
return super.put(key, value);
}
真实实现:
@Override
public boolean put(@Nullable K key, @Nullable V value) {
Collection<V> collection = map.get(key);
if (collection == null) {
collection = createCollection(key);
if (collection.add(value)) {
totalSize++;
map.put(key, collection);
return true;
} else {
throw new AssertionError("New Collection " +
"violated the Collection spec");
}
} else if (collection.add(value)) {
totalSize++;
return true;
} else {
return false;
}
}
实现步骤:(1)、从map中获取key所对应的value集合,并存放在collection中;
(2)、如果map中没有对应的key则collection将为null,这时需要为key对应的value申请存储的空间,并将申请到的地址赋值给collection。将本次添加的value添加到collection中,如果添加成功,则totalSize需要加一,并将key和collection添加到map中去返回;如果value添加到collection中失败了,则抛出AssertionError的错误。
(3)、如果collection不为空,则直接将value添加到collection中。如果添加成功,则totalSize需要加一并返回true;如果添加失败,则返回false。
(完)
本博客文章除特别声明,全部都是原创!原创文章版权归过往记忆大数据(过往记忆)所有,未经许可不得转载。
本文链接: 【Guava学习之AbstractSetMultimap】(https://www.iteblog.com/archives/753.html)

