[Java] 浅析Google Guava Multimap

news/2024/7/3 8:18:53

类关系

ArrayListMultiMap.java

Multimap <I>
|
|
AbstractMultimap <A>                  Serializable <I>    
|__________________________________________|
|
AbstractMapBasedMultimap <A>  
|
|
AbstractListMultimap <A>              ListMultimap <I>
|__________________________________________|
|
ArrayListMultiMap

LinkedListMultiMap.java

Multimap <I>
|
|
AbstractMultimap <A>              ListMultimap <I>                 Serializable <I>
|__________________________________________|______________________________|
|
LinkedListMultimap

TreeMultimap.java

Multimap <I>
|
|
AbstractMultimap <A>                  Serializable <I>    
|__________________________________________|
|
AbstractMapBasedMultimap <A>          SetMultimap <I>    
|__________________________________________|
|
AbstractSetMultimap <A>              SortedSetMultimap <I>
|__________________________________________|
|
AbstractSortedSetMultimap <A> 
|
|
AbstractSortedKeySortedSetMultimap <A>
|
|
TreeMultimap

实现方法

ArrayListMultimap

ArrayListMultiMap.java是以ArrayList为Collection的特定实现,这个类中没有太多的实际代码,主要是createCollection()方法中特定的产生一个ArrayList作为Collection。

AbstractListMultimap.java是AbstractMultimap的一个List专有版本,这个类和ListMultimap接口一起,将Multimap的方法都重写为List。

AbstractMapBasedMultimap.java则是所有以Map为核心的Multimap的基本实现,这里实现了所有Multimap的方法,是最重要的一部分。

clear方法,先将每个collection清空,再把map清空

public void clear() {
    // Clear each collection, to make previously returned collections empty.
    for (Collection<V> collection : map.values()) {
      collection.clear();
    }
    map.clear();
    totalSize = 0;
}

put方法,我们可以发现这里的size是每多一个KV对就加1,而不是唯一Key的数量,这点和Map不同

public boolean put(@Nullable K key, @Nullable V value) {
    Collection<V> collection = map.get(key);
    // 如果这是一个新key没有对应的Collection
    if (collection == null) {
      // 先根据子类实现创建一个相应的Collection
      collection = createCollection(key);
      // 将KV对加入Map中
      if (collection.add(value)) {
        totalSize++;
        map.put(key, collection);
        return true;
      } else {
        throw new AssertionError("New Collection violated the Collection spec");
      }
    // 如果已经有这个key了,就加入它的Collection
    } else if (collection.add(value)) {
      totalSize++;
      return true;
    } else {
      return false;
    }
}

removeAll方法,需要返回删除的Value,所以要一个临时变量存起来

public Collection<V> removeAll(@Nullable Object key) {
    // 先将Key移出
    Collection<V> collection = map.remove(key);
    // 如果Value为空,则返回空集合
    if (collection == null) {
      return createUnmodifiableEmptyCollection();
    }
    // 否则将Value的值拷贝到输出集合中,再把Value清空
    Collection<V> output = createCollection();
    output.addAll(collection);
    totalSize -= collection.size();
    collection.clear();
    // 返回输出集合
    return unmodifiableCollectionSubclass(output);
}

size方法,注意这里返回的是KV数,而非K的唯一个数

public int size() {
    return totalSize;
}

isEmpty方法,判断KV数是否为0

public boolean isEmpty() {
    return size() == 0;
}

get方法

public Collection<V> get(@Nullable K key) {
    Collection<V> collection = map.get(key);
    // 如果没有Value就新建一个Collection
    if (collection == null) {
      collection = createCollection(key);
    }
    return wrapCollection(key, collection);
}    

AbstractMultimap.java也实现了一些基本方法,和上一个文件一起涵盖了所有API

remove方法

public boolean remove(@Nullable Object key, @Nullable Object value) {
    // 从Map中按照key找到该集合
    Collection<V> collection = asMap().get(key);
    // 如果集合不为空,则找到集合中的这个值并删除
    return collection != null && collection.remove(value);
}

putAll方法,以key为第一参数,以一个Iterable为第二参数

public boolean putAll(@Nullable K key, Iterable<? extends V> values) {
    checkNotNull(values);
    // make sure we only call values.iterator() once
    // and we only call get(key) if values is nonempty
    if (values instanceof Collection) {
      Collection<? extends V> valueCollection = (Collection<? extends V>) values;
      // 拿出Collection然后把新的addAll进去
      return !valueCollection.isEmpty() && get(key).addAll(valueCollection);
    } else {
      Iterator<? extends V> valueItr = values.iterator();
      // 拿出Iterator然后把新的addAll进去
      return valueItr.hasNext() && Iterators.addAll(get(key), valueItr);
    }
}

putAll方法,以另一个Multimap为参数

public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
    boolean changed = false;
    for (Map.Entry<? extends K, ? extends V> entry : multimap.entries()) {
      changed |= put(entry.getKey(), entry.getValue());
    }
    return changed;
}

replace方法

public Collection<V> replaceValues(@Nullable K key, Iterable<? extends V> values) {
    checkNotNull(values);
    // 先移除所有
    Collection<V> result = removeAll(key);
    // 在加入新的值
    putAll(key, values);
    return result;
}

containsValue方法

public boolean containsValue(@Nullable Object value) {
    // 检查每一个Collection是否有这个值
    for (Collection<V> collection : asMap().values()) {
      if (collection.contains(value)) {
        return true;
      }
    }
    return false;
}

containsEntry方法,实际上是用get来判断是否有这个key,然后再看是否有这个值

public boolean containsEntry(@Nullable Object key, @Nullable Object value) {
    Collection<V> collection = asMap().get(key);
    return collection != null && collection.contains(value);
}

http://www.niftyadmin.cn/n/1982553.html

相关文章

CPU亲缘性及网卡中断绑定

#####编辑器依旧那么难用 难用 难用~~##################################################################CPU亲缘性及网卡中断绑定每个CPU的每个核心都会被识别成一个逻辑CPU&#xff0c;由一个核心会存在超线程的功能&#xff0c;所以一个物理核心会表现成为多个cpu多个cpu…

JavaSE基础知识(十六)--Java的类的访问权限(单例模式初步)

Java SE 是什么&#xff0c;包括哪些内容(十六)&#xff1f; 本文内容参考自Java8标准 在此特别感谢Java编程思想一书对本文的启发&#xff01; 1、接口和实现 看到这里&#xff0c;那么在你以后的编程生涯中&#xff0c;你都需要牢记一点&#xff0c;尽量将接口和实现分离&…

idea goland 插件 struct to struct

go-struct-to-struct idea goland 插件。实现自动生成 struct 间 转换代码。 https://plugins.jetbrains.com/plugin/22196-struct-to-struct/ IntelliJ plugin that Automatically generate two struct transformations through function declarations Usage define func …

JavaSE基础知识(十七)--Java复用代码之组合与继承

Java SE 是什么&#xff0c;包括哪些内容(十七)&#xff1f; 本文内容参考自Java8标准 再次感谢Java编程思想对本文的启发&#xff01; 复用代码是Java众多引人注目的功能之一&#xff0c;但要想成为极具革命性的语言&#xff0c;仅仅能够复制代码并对之加以改变是不够的(也就…

eclipse HttpServlet 类会报错

2019独角兽企业重金招聘Python工程师标准>>> 以前的eclipse因为更换电脑的位数&#xff0c;启动时会出现Failed to load the JNI shared library的错误&#xff0c;好像是和jdk位数&#xff08;32位或64&#xff09;有关系 重新copy了一个eclipse导进去项目遇到以下…

JavaSE基础知识(十七)--Java复用代码之静态代理

Java SE 是什么&#xff0c;包括哪些内容(十七)&#xff1f; 本文内容参考自Java8标准 再次感谢Java编程思想对本文的启发&#xff01; Java中复用代码的方式&#xff0c;除了之前博文中提到过的组合和继承之外&#xff0c;还有第三种&#xff1a;代理&#xff0c;而代理又分为…

JavaSE基础知识(十七)--Java复用代码之动态代理

Java SE 是什么&#xff0c;包括哪些内容(十七)&#xff1f; 本文内容参考自Java8标准 再次感谢Java编程思想对本文的启发&#xff01; 上一篇博文中详细说明了静态代理的内容&#xff0c;也指出了静态代理只适合小范围的使用(使用和维护都很麻烦)&#xff0c;真正强大的是动态…

JavaSE基础知识(十七)--Java动态代理中InvocationHandler中Object类型参数proxy的作用

Java SE 是什么&#xff0c;包括哪些内容(十七)&#xff1f; 本文内容参考自Java8标准 再次感谢Java编程思想对本文的启发&#xff01; 上一篇博文中详细说明了动态代理的内容&#xff0c;但是在说到调用处理器InvocationHandler的时候&#xff0c;有一个Object类型的参数prox…