亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java項目Guava包?HashMultimap使用及注意事項

 更新時間:2022年05月26日 09:18:38   作者:一灰灰  
guava基本上可以說是java開發(fā)項目中,大概率會引入的包,今天介紹的主角是一個特殊的容器HashMultmap,可以簡單的將它的數(shù)據(jù)結(jié)構(gòu)理解為Map<K,?Set<V>>,今天主要介紹下基礎(chǔ)的知識點?HashMultmap級使用,感興趣的朋友一起看看吧

今天給大家介紹一個相對基礎(chǔ)的知識點 HashMultmap;

guava基本上可以說是java開發(fā)項目中,大概率會引入的包,今天介紹的主角是一個特殊的容器 -- HashMultmap,可以簡單的將它的數(shù)據(jù)結(jié)構(gòu)理解為Map<K, Set<V>>

那么為什么會突然想到介紹一下它呢,因為昨天剛因為對它理解不夠深刻,把它當作了Map<K, List<V>>來使用,結(jié)果出了問題;既然如此那就好好盤一盤,反思一下

1. 數(shù)據(jù)模型介紹

正常來講,在使用一個新的數(shù)據(jù)對象時,我們應(yīng)該先的了解它的數(shù)據(jù)模型;

直接看源碼,會發(fā)現(xiàn)實際存儲數(shù)據(jù)的結(jié)構(gòu)為 Map<K, Collection<V>>

abstract class AbstractMapBasedMultimap<K, V> extends AbstractMultimap<K, V> implements Serializable {
    private transient Map<K, Collection<V>> map;
}

再jdk中Map也有很多實現(xiàn),那么具體是哪個呢?

從構(gòu)造方法出發(fā),來看下這個map成員的初始化過程

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

private HashMultimap(Multimap<? extends K, ? extends V> multimap) {
    super(Platform.newHashMapWithExpectedSize(multimap.keySet().size()));
    this.expectedValuesPerKey = 2;
    this.putAll(multimap);
}

關(guān)鍵點就在 Platform.newHashMapWithExpectedSize,熟悉的小伙伴已經(jīng)能很快給出答案了,這個map就是我們常用的HashMap

接下來需要關(guān)注的就是value中的Collection,是什么容器類型了;對于它,則從添加元素的時候來定位put(key, value)

關(guān)鍵源碼如下

public boolean put(@Nullable K key, @Nullable V value) {
    Collection<V> collection = (Collection)this.map.get(key);
    if (collection == null) {
        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;
    }
}

這個寫法相信大家都不會陌生,存在時,直接添加到容器;不存在時,則通過 createCollection來創(chuàng)建容器,并塞入Map;其具體的實現(xiàn)邏輯如下

// com.google.common.collect.HashMultimap#createCollection
Set<V> createCollection() {
    return Platform.newHashSetWithExpectedSize(this.expectedValuesPerKey);
}

所以HashMultimap的底層數(shù)據(jù)存儲就是我們的老朋友 HashMap<K, HashSet<V>>

2. 簡單使用介紹

基本來講,HashMultimap的使用姿勢非常簡單了,下面給出簡單實例演示一下,基本上看看就會了

2.1 容器創(chuàng)建

// 創(chuàng)建一個默認的 HashMap<String, Set<Integer>>,容器的初始化容量與HashMap的默認值一樣
HashMultimap<String, Integer> map = HashMultimap.create();

// 當我們知道容器的個數(shù)時,推薦使用下面這種方式, 
// HashMap 設(shè)置容量為8, 每個HashSet的容量初始化為16
HashMultimap<String, Integer> map2 = HashMultimap.create(8, 16);

// 另外一個就是基于MultMap來創(chuàng)建的case了
HashMultimap<String, Integer> map3 = HashMultimap.create(map);

注意上面的第三種實現(xiàn),需要理解的是 map3.get(key) != map.get(key)

即基于原來的容器初始化的新容器,其value是一個新的容器對象,將之前的value中所有元素,都塞入新的容器中,并不是直接引用就的容器對象(這么一說是不是更想是深拷貝,而不是淺拷貝呢?)

2.2 添加元素

// 添加單個元素
map.put("hello", 510);
// 添加多個元素
map.putAll("skill", Arrays.asList(1, 2, 3, 4, 1));

注意

  • 因為value是HashSet,所以重復(fù)的元素會忽略
  • 塞入重復(fù)的元素會忽略
  • 再次申明,添加重復(fù)的元素會忽略

(沒錯,我就是這里出了問題......)

2.3 移除元素

// 移除skill對應(yīng)的集合中,value=3的元素
map.remove("skill", 3);
// 移除key
map.removeAll("hello");

2.4 替換元素

如果我們希望將整個value都換成一個新的集合,那么可以使用replaceValue

// 直接替換skill對應(yīng)的value集合,新的值為 {100, 200, 300}
map.replaceValues("skill", Arrays.asList(100, 200, 300));

2.5 獲取元素及遍歷

// 獲取對應(yīng)的value集合,當不存在時,返回空集合(不是null,簡直是貼心)
Set<Integer> set = map.get("skill");

foreach方式的迭代

for (Map.Entry<String, Integer> entry: map.entries()) {
    System.out.println(entry.getKey() + ":" + entry.getValue());
}

注意上面的迭代成員 Map.Entry<String, Integer>,其key依然是HashMap的key,而value則是這個集合中的沒一個元素,比如容器中的值為("skill": [100,200,300])時,此時輸出如下

skill:200
skill:100
skill:300

2.6 輸出所有的key

// 輸出所有的key,
map.keys()
// 輸出key集合
map.keySet();

他們兩有啥區(qū)別?看個實例

HashMultimap<String, Integer> map = HashMultimap.create();
map.replaceValues("skill", Arrays.asList(100, 200, 300));
System.out.println("keys=" + map.keys());
System.out.println("keySet=" + map.keySet());

輸出如下

keys=[skill x 3]
keySet=[skill]

上面這個skill x 3是什么鬼,實際上表示skill有三個,返回的容器可以理解為List,不去重

而下面的KeySet()則返回的是個Set,會去重

2.7 輸出所有的value

map.values()

通過上面的再理解這個就簡單了,所有的value都合并再一個List,接下來我們看一下兩種遍歷方式

HashMultimap<String, Integer> map = HashMultimap.create();
map.putAll("skill", Arrays.asList(100, 200, 300));
map.put("a", 100);
for (Integer v: map.values()) {
    System.out.println(v);
}

實際輸出如下

100
100
200
300

3. 小結(jié)

這里主要介紹的是Gauva的容器HashMultimap的數(shù)據(jù)模型及使用姿勢,知識點相對來說比較基礎(chǔ),再實際使用的時候,請牢記,把它看作是簡單方便易使用的 HashMap<K, HashSet<V>> 即可,重點注意value中的元素不能重復(fù)即可

那么當我們希望value是個List時,可以怎么整呢?

  • 此時可以使用 LinkedMultiValueMap 來替代,它的底層數(shù)據(jù)結(jié)構(gòu)實際就是 HashMap<K, LinkedHashMap<V>>
  • 使用 ArrayListMultimap 也可以,底層數(shù)據(jù)結(jié)構(gòu)為 HashMap<K, ArrayList<V>>

最后提一句,guava的這幾個容器的實現(xiàn),其源碼閱讀起來不會吃力,且設(shè)計思路也非常典型,比如如果讓我們自己來基于jdk的基礎(chǔ)容器實現(xiàn)一個類似的容器,如何優(yōu)雅的去實現(xiàn)呢? 這里就給了一個標準答案,強烈推薦有興趣的小伙伴瞅一下

到此這篇關(guān)于Java項目Guava包 HashMultimap使用及注意事項的文章就介紹到這了,更多相關(guān)java HashMultimap使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論