Guava源码解析十三:Multimap源码解析

Multimap相对于传统的Map区别在于,Multimap是一对多的一个数据结构,对于Multimap的解析用HashMultimap进行解析,看一下HashMultimap的类结构图:

HashMultimap构造器

因为他的构造方法是私有的,所有他会拥有静态方法构造器:

public static <K, V> HashMultimap<K, V> create() {
	//new一个HashMultimap,不传入任何值
    return new HashMultimap();
}
public static <K, V> HashMultimap<K, V> create(int expectedKeys, int expectedValuesPerKey) {
	//new一个HashHultimap,传入两个值,一个是期望key的长度,另一个是期望value的长度
    return new HashMultimap(expectedKeys, expectedValuesPerKey);
}
public static <K, V> HashMultimap<K, V> create(Multimap<? extends K, ? extends V> multimap) {
	//传入一个Multimap值
    return new HashMultimap(multimap);
}

看到了三个静态构造方法之后,了解到三个构造方法都调用了私有的构造器,所以看一下私有构造器的源码:

private HashMultimap() {
    //new一个新的map然后交给父类处理
    super(new HashMap());
}
private HashMultimap(int expectedKeys, int expectedValuesPerKey) {
    //获取一个长度为4/3的expectedKeys 的map然后交给父类处理
    super(Maps.newHashMapWithExpectedSize(expectedKeys));
    Preconditions.checkArgument(expectedValuesPerKey >= 0);
    this.expectedValuesPerKey = expectedValuesPerKey;
}
private HashMultimap(Multimap<? extends K, ? extends V> multimap) {
    //获取一个长度为4/3multimap的长度的map交给父类处理
    super(Maps.newHashMapWithExpectedSize(multimap.keySet().size()));
    this.putAll(multimap);
}

可以看到三个私有构造方法都调用了父类的构造方法,接下来看看父类的构造器源码,发现最后的Multimap的数据结构也体现在AbstractMapBasedMultimap这个类中,所以看一下这个类的构造器个变量:

//底层数据结构是一个key为一个Object类,value为一个容器
private transient Map<K, Collection<V>> map;
//Multimap总长度
private transient int totalSize;
protected AbstractMapBasedMultimap(Map<K, Collection<V>> map) {
    Preconditions.checkArgument(map.isEmpty());
    this.map = map;
}

 

功能方法

看到了AbstractMapBasedMultimap的源码发现Multimap的put、get逻辑也是在这个类中实现的:

put方法的实现

public boolean put(@Nullable K key, @Nullable V value) {
//首先在map容器中查看是否有这个key值存在。
Collection collection = (Collection)this.map.get(key);
//如果collection为null,则说明这个key值在map容器中不存在
if(collection == null) {
    //根据这个key创建一个容器
    collection = this.createCollection(key);
    //然后将value放在这个容器中
    if(collection.add(value)) {
        ++this.totalSize;
        this.map.put(key, collection);
        return true;
    } else {
        throw new AssertionError("New Collection violated the Collection spec");
    }
    //如果这个容器存在则直接放入value值
    } else if(collection.add(value)) {
        ++this.totalSize;
        return true;
    } else {
        return false;
    }
}

get方法的实现

public Collection<V> get(@Nullable K key) {
	//首先在map容器中查看是否有这个key值存在。
    Collection collection = (Collection)this.map.get(key);
    //如果为null,则为其创建一个容器
    if(collection == null) {
        collection = this.createCollection(key);
    }
    //根据本类的wrapCollection方法找到并返回一个集合类
    return this.wrapCollection(key, collection);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值