栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Guava源码阅读:Multimap相关

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Guava源码阅读:Multimap相关

使用场景

开始之前我先发一个题目:

有一份日志记录,每条记录的内容是一个url,每个url都是AAA/BBB/CCC形式,我现在想得到每个url按照AAA分组,并且在按照分组形势输出每个分组中的所有数据

以下是我第一次遇到这个问题的解法:

        HashMap> ansFor4 = new HashMap<>(16);
        while((lineInformation = bufferedReader.readLine()) != null){
        int o = key[1].indexOf("/", 1);
        if(o == -1) {
            continue;
        }
        ansFor4Str1 = key[1].substring(1, o);
        ansFor4Str2 = key[1].substring(o + 1);
        if(!ansFor4.containsKey(ansFor4Str1)){
            ansFor4.put(ansFor4Str1, new HashSet<>());
        }
        ansFor4.get(ansFor4Str1).add(ansFor4Str2);

思路很简单,创建一个Map>的集合就可以解决该问题,不过对该数据结构进行操作的时候难免比较麻烦,这时候就可以使用Multimap组件下的数据结构,它的方法包含以上所有操作。

源码 构造方法

选择我比较熟悉的hash,从HashMultimap开始,进入代码:

	// 以下三个是构造方法,都调用了对应的私有构造器
    public static  HashMultimap create() {
        return new HashMultimap();
    }

    public static  HashMultimap create(int expectedKeys, int expectedValuesPerKey) {
        return new HashMultimap(expectedKeys, expectedValuesPerKey);
    }

    public static  HashMultimap create(Multimap multimap) {
        return new HashMultimap(multimap);
    }

	// 私有构造器
    private HashMultimap() {
        super(new HashMap());
    }

    private HashMultimap(int expectedKeys, int expectedValuesPerKey) {
        super(Maps.newHashMapWithExpectedSize(expectedKeys));
        Preconditions.checkArgument(expectedValuesPerKey >= 0);
        this.expectedValuesPerKey = expectedValuesPerKey;
    }

    private HashMultimap(Multimap multimap) {
        super(Maps.newHashMapWithExpectedSize(multimap.keySet().size()));
        this.putAll(multimap);
    }

选择最简单的一个,点进super看看?
会依次进入HashMultimapGwtSerializationDependencies、AbstractSetMultimap、AbstractMapBasedMultimap,最后的实现就在AbstractMapBasedMultimap中

	// map的定义,如果你思考了上面那道题,一定不会对这个数据结构感到奇怪
	private transient Map> map;
	// 构建
    protected AbstractMapBasedMultimap(Map> map) {
        Preconditions.checkArgument(map.isEmpty());
        this.map = map;
    }

	// Preconditions.checkArgument(boo)方法,异常处理
    public static void checkArgument(boolean expression) {
        if (!expression) {
            throw new IllegalArgumentException();
        }
    }
看看其他方法
	//返回set集合
    Set createCollection() {
        return Sets.newHashSetWithExpectedSize(this.expectedValuesPerKey);
    }
    
    // IO,输入输出
    @GwtIncompatible
    private void writeObject(ObjectOutputStream stream) throws IOException {
        stream.defaultWriteObject();
        Serialization.writeMultimap(this, stream);
    }

    @GwtIncompatible
    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
        stream.defaultReadObject();
        this.expectedValuesPerKey = 2;
        int distinctKeys = Serialization.readCount(stream);
        Map> map = Maps.newHashMap();
        this.setMap(map);
        Serialization.populateMultimap(this, stream, distinctKeys);
    }

看到这里我很好奇,最重要的增删改查呢?接着在父类中寻找发现,增删改查是在AbstractMapBasedMultimap中实现了

put方法

	// put的过程和我之前数据结构的增加操作基本相似
	// 首先查看要加入的key在集合中是否存在,如果不存在,创建一个
	// 如果存在,直接加入容器
    public boolean put(@Nullable K key, @Nullable V value) {
        Collection collection = (Collection)this.map.get(key);
        if (collection == null) {
        	// 以下就是创建并且把value加入的过程
            collection = this.createCollection(key);
            if (collection.add(value)) {
                ++this.totalSize;
                this.map.put(key, collection);
                return true;
            } else {
            	// 异常处理
                throw new AssertionError("New Collection violated the Collection spec");
            }
        } else if (collection.add(value)) {
            ++this.totalSize;
            return true;
        } else {
            return false;
        }
    }

get方法

    public Collection get(@Nullable K key) {
        Collection collection = (Collection)this.map.get(key);
        // 如果没有找到对应集合,创建一个
        if (collection == null) {
            collection = this.createCollection(key);
        }

        return this.wrapCollection(key, collection);
    }
实现区别

在AbstractMapBasedMultimap中只是最基础的实现,你会看到这里面的方法虽然实现了但是还有很多重写。以put举例,有AbstractListMultimap以及AbstractSetMultimap两种重写

	//AbstractListMultimap中的put方法
    @CanIgnoreReturnValue
    public boolean put(@Nullable K key, @Nullable V value) {
        return super.put(key, value);
    }
    
	//AbstractSetMultimap中的put方法
    @CanIgnoreReturnValue
    public boolean put(@Nullable K key, @Nullable V value) {
        return super.put(key, value);
    }

这两不一样的吗?
对,不过他们的value实现不一样,一个是List,另一个则是Map。其中,AbstractSetMultimap的实现之一就是一开始的HashMultimap,而AbstractListMultimap的继承者是ArrayListMultimap等

暑期编程PK赛 得CSDN机械键盘等精美礼品!
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1017541.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号