这篇文章是续着昨天的《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)