欢迎关注大数据技术架构与案例微信公众号:过往记忆大数据
过往记忆博客公众号iteblog_hadoop
欢迎关注微信公众号:
过往记忆大数据

Guava学习之AbstractSetMultimap

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

  注意:如果collection不为空,这里只是将value添加到collection中,然后就完事了。这是因为collection = map.get(key);返回的collection返回的是key对应value的存储空间的一个视图,任何对collection的操作将会影响到key的value,所以不需要再map.put(key, collection);

(完)

本博客文章除特别声明,全部都是原创!
原创文章版权归过往记忆大数据(过往记忆)所有,未经许可不得转载。
本文链接: 【Guava学习之AbstractSetMultimap】(https://www.iteblog.com/archives/753.html)
喜欢 (5)
分享 (0)
发表我的评论
取消评论

表情
本博客评论系统带有自动识别垃圾评论功能,请写一些有意义的评论,谢谢!
(1)个小伙伴在吐槽