Java?Multimap實現(xiàn)類與操作的具體示例
一、Multimap 概述
Multimap 是 Google Guava 庫中提供的一種集合類型,它擴展了傳統(tǒng)的 Map 概念,允許一個鍵對應多個值。與標準的 Map<K, List<V>>
或 Map<K, Set<V>>
相比,Multimap 提供了更簡潔的 API 和更強大的功能。
Multimap 主要特點:
- 一個鍵可以映射到多個值
- 避免了手動管理值集合的麻煩
- 提供了豐富的視圖集合
- 支持不可變實現(xiàn)
二、Multimap 實現(xiàn)類
Guava 提供了多種 Multimap 實現(xiàn),每種實現(xiàn)都有不同的特性和使用場景。
1. ListMultimap 系列
特點:值以 List 形式存儲,允許重復值,保留插入順序
實現(xiàn)類 | 描述 | 是否線程安全 |
---|---|---|
ArrayListMultimap | 使用 ArrayList 作為值集合 | 否 |
LinkedListMultimap | 使用 LinkedList 作為值集合 | 否 |
ImmutableListMultimap | 不可變實現(xiàn) | 是 |
2. SetMultimap 系列
特點:值以 Set 形式存儲,不允許重復值
實現(xiàn)類 | 描述 | 是否線程安全 |
---|---|---|
HashMultimap | 使用 HashSet 作為值集合 | 否 |
LinkedHashMultimap | 使用 LinkedHashSet 作為值集合,保留插入順序 | 否 |
TreeMultimap | 使用 TreeSet 作為值集合,按鍵和值排序 | 否 |
ImmutableSetMultimap | 不可變實現(xiàn) | 是 |
3. 其他實現(xiàn)
實現(xiàn)類 | 描述 | 是否線程安全 |
---|---|---|
Multimaps.synchronizedMultimap | 同步包裝器,使任何 Multimap 線程安全 | 是 |
Multimaps.unmodifiableMultimap | 不可修改視圖 | 是 |
三、Multimap 基本操作示例
1. 創(chuàng)建 Multimap
// 創(chuàng)建ArrayListMultimap ListMultimap<String, String> listMultimap = ArrayListMultimap.create(); // 創(chuàng)建HashMultimap SetMultimap<String, Integer> setMultimap = HashMultimap.create(); // 創(chuàng)建不可變Multimap ImmutableListMultimap<String, String> immutableMultimap = ImmutableListMultimap.of( "key1", "value1", "key1", "value2", "key2", "value3" );
2. 添加元素
ListMultimap<String, String> multimap = ArrayListMultimap.create(); // 添加單個元素 multimap.put("fruit", "apple"); multimap.put("fruit", "banana"); multimap.put("fruit", "orange"); multimap.put("vegetable", "carrot"); // 添加多個元素 multimap.putAll("fruit", Arrays.asList("pear", "grape")); multimap.putAll("vegetable", Arrays.asList("potato", "tomato"));
3. 獲取元素
// 獲取某個鍵的所有值 List<String> fruits = multimap.get("fruit"); // [apple, banana, orange, pear, grape] // 獲取第一個值 String firstFruit = multimap.get("fruit").get(0); // apple // 檢查鍵是否存在 boolean hasFruit = multimap.containsKey("fruit"); // true // 檢查鍵值對是否存在 boolean hasApple = multimap.containsEntry("fruit", "apple"); // true
4. 刪除元素
// 刪除鍵的所有值 multimap.removeAll("fruit"); // 返回被刪除的值列表 // 刪除特定鍵值對 multimap.remove("vegetable", "tomato"); // 返回boolean表示是否刪除成功 // 清空所有元素 multimap.clear();
5. 視圖操作
// 獲取所有鍵的集合(去重) Set<String> keys = multimap.keySet(); // 獲取所有值的集合(不去重) Collection<String> values = multimap.values(); // 獲取鍵值對集合 Collection<Map.Entry<String, String>> entries = multimap.entries(); // 將Multimap轉換為Map<K, Collection<V>> Map<String, Collection<String>> mapView = multimap.asMap();
四、不同實現(xiàn)類的具體示例
1. ArrayListMultimap 示例
// 創(chuàng)建ArrayListMultimap ListMultimap<String, Integer> scores = ArrayListMultimap.create(); // 添加元素 scores.put("Alice", 90); scores.put("Alice", 85); scores.put("Bob", 75); scores.put("Bob", 80); scores.put("Bob", 82); // 獲取元素 List<Integer> aliceScores = scores.get("Alice"); // [90, 85] List<Integer> bobScores = scores.get("Bob"); // [75, 80, 82] // 允許重復值 scores.put("Alice", 90); List<Integer> newAliceScores = scores.get("Alice"); // [90, 85, 90]
2. HashMultimap 示例
// 創(chuàng)建HashMultimap SetMultimap<String, String> tags = HashMultimap.create(); // 添加元素 tags.put("article1", "tech"); tags.put("article1", "java"); tags.put("article1", "programming"); tags.put("article2", "design"); tags.put("article2", "ui"); // 嘗試添加重復值 tags.put("article1", "java"); // 不會有任何效果 // 獲取元素 Set<String> article1Tags = tags.get("article1"); // [tech, java, programming] Set<String> article2Tags = tags.get("article2"); // [design, ui]
3. TreeMultimap 示例
// 創(chuàng)建TreeMultimap(按鍵和值排序) TreeMultimap<String, Integer> sortedScores = TreeMultimap.create(); // 添加元素(亂序) sortedScores.put("Bob", 80); sortedScores.put("Alice", 90); sortedScores.put("Bob", 75); sortedScores.put("Alice", 85); // 獲取元素(自動排序) SortedSet<Integer> aliceSortedScores = sortedScores.get("Alice"); // [85, 90] SortedSet<Integer> bobSortedScores = sortedScores.get("Bob"); // [75, 80] // 整個Multimap也是按鍵排序的 System.out.println(sortedScores); // {Alice=[85, 90], Bob=[75, 80]}
4. ImmutableListMultimap 示例
// 創(chuàng)建不可變Multimap ImmutableListMultimap<String, String> immutableMap = ImmutableListMultimap.<String, String>builder() .put("colors", "red") .put("colors", "green") .put("colors", "blue") .put("shapes", "circle") .put("shapes", "square") .build(); // 嘗試修改會拋出UnsupportedOperationException // immutableMap.put("colors", "yellow"); // 錯誤! // 安全地獲取數(shù)據(jù) List<String> colors = immutableMap.get("colors"); // [red, green, blue]
五、高級操作與工具方法
1. 使用 Multimaps 工具類
// 從Map<K, Collection<V>>創(chuàng)建Multimap Map<String, List<Integer>> map = new HashMap<>(); map.put("a", Arrays.asList(1, 2, 3)); map.put("b", Arrays.asList(4, 5)); ListMultimap<String, Integer> multimap = Multimaps.forMap(map); // 轉換Multimap的值類型 ListMultimap<String, String> stringMultimap = ArrayListMultimap.create(); stringMultimap.put("key", "1"); stringMultimap.put("key", "2"); ListMultimap<String, Integer> intMultimap = Multimaps.transformValues(stringMultimap, Integer::valueOf); // 反轉Multimap(鍵值互換) SetMultimap<Integer, String> inverted = Multimaps.invertFrom(stringMultimap, HashMultimap.create());
2. 過濾操作
ListMultimap<String, Integer> scores = ArrayListMultimap.create(); scores.put("Alice", 90); scores.put("Alice", 85); scores.put("Bob", 75); scores.put("Bob", 80); // 過濾出分數(shù)大于80的條目 Multimap<String, Integer> highScores = Multimaps.filterEntries(scores, entry -> entry.getValue() > 80); System.out.println(highScores); // {Alice=[90, 85]}
3. 同步包裝
ListMultimap<String, String> unsafeMultimap = ArrayListMultimap.create(); // 創(chuàng)建線程安全版本 ListMultimap<String, String> safeMultimap = Multimaps.synchronizedListMultimap(unsafeMultimap); // 現(xiàn)在可以安全地在多線程環(huán)境中使用 safeMultimap.put("key", "value");
六、性能比較與選擇指南
實現(xiàn)類 | 鍵存儲 | 值存儲 | 允許重復值 | 順序保證 | 典型用途 |
---|---|---|---|---|---|
ArrayListMultimap | HashMap | ArrayList | 是 | 插入順序 | 需要保留插入順序且允許重復值的場景 |
LinkedListMultimap | LinkedHashMap | LinkedList | 是 | 插入順序 | 需要頻繁在中間插入/刪除的場景 |
HashMultimap | HashMap | HashSet | 否 | 無 | 需要快速查找且不需要重復值的場景 |
LinkedHashMultimap | LinkedHashMap | LinkedHashSet | 否 | 插入順序 | 需要保留插入順序且不允許重復值的場景 |
TreeMultimap | TreeMap | TreeSet | 否 | 排序順序 | 需要按鍵和值排序的場景 |
ImmutableListMultimap | 不可變 | 不可變 | 是 | 構造順序 | 需要不可變集合的場景 |
ImmutableSetMultimap | 不可變 | 不可變 | 否 | 構造順序 | 需要不可變集合且不允許重復值的場景 |
選擇建議:
- 如果需要允許重復值 - 選擇 ListMultimap 實現(xiàn)
- 如果需要快速查找且不允許重復值 - 選擇 SetMultimap 實現(xiàn)
- 如果需要排序功能 - 選擇 TreeMultimap
- 如果需要線程安全 - 使用不可變實現(xiàn)或同步包裝器
- 如果數(shù)據(jù)不常變化 - 優(yōu)先考慮不可變實現(xiàn)
七、常見問題解答
Q1: Multimap 和 Map<K, List> 有什么區(qū)別?
A1: 主要區(qū)別在于:
- Multimap 提供了更簡潔的 API,不需要手動管理值集合
- Multimap 提供了豐富的視圖方法(如 entries(), keys(), values())
- Multimap 隱藏了實現(xiàn)細節(jié),可以更靈活地切換底層實現(xiàn)
- Multimap 的方法更直觀,如 put() 直接添加元素而不需要先檢查是否存在集合
Q2: 如何將 Multimap 轉換為傳統(tǒng)的 Map?
A2: 可以使用 asMap() 方法:
ListMultimap<String, String> multimap = ArrayListMultimap.create(); multimap.put("key", "value1"); multimap.put("key", "value2"); Map<String, Collection<String>> map = multimap.asMap();
Q3: Multimap 是線程安全的嗎?
A3: 大多數(shù) Multimap 實現(xiàn)不是線程安全的,除了:
- 不可變實現(xiàn)(ImmutableListMultimap, ImmutableSetMultimap)
- 使用 Multimaps.synchronizedMultimap() 包裝的 Multimap
Q4: 如何統(tǒng)計 Multimap 中每個鍵對應的值數(shù)量?
A4: 可以使用 Multimap 的 keys() 方法結合 Multisets:
ListMultimap<String, String> multimap = ArrayListMultimap.create(); // 添加元素... Multiset<String> counts = HashMultiset.create(multimap.keys()); System.out.println(counts); // 顯示每個鍵的出現(xiàn)次數(shù)
八、總結
Guava 的 Multimap 提供了一種優(yōu)雅的方式來處理鍵到多個值的映射關系,比傳統(tǒng)的 Map<K, Collection<V>>
更加方便和強大。通過選擇合適的實現(xiàn)類,可以滿足各種不同的業(yè)務需求,包括是否需要允許重復值、是否需要保持順序、是否需要排序等功能。
在實際開發(fā)中,Multimap 特別適用于以下場景:
- 標簽系統(tǒng)(一個項目有多個標簽)
- 學生成績記錄(一個學生有多門成績)
- 反向索引(一個單詞出現(xiàn)在多個文檔中)
- 分組統(tǒng)計(按類別分組記錄)
掌握 Multimap 的使用可以顯著簡化代碼,提高開發(fā)效率,是 Java 開發(fā)者工具箱中不可或缺的工具之一。
到此這篇關于Java Multimap實現(xiàn)類與操作具體示例的文章就介紹到這了,更多相關Java Multimap類操作示例內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring核心容器之ApplicationContext上下文啟動準備詳解
這篇文章主要介紹了Spring核心容器之ApplicationContext上下文啟動準備詳解,ApplicationContext 繼承自 BeanFactory ,其不僅包含 BeanFactory 所有功能,還擴展了容器功能,需要的朋友可以參考下2023-11-11Java 8對LinkedHashSet元素進行排序的操作方法
LinkedHashSet 是 Java 集合框架中的一個類,它繼承自 HashSet,并實現(xiàn)了 Set 接口,然而,LinkedHashSet 不支持元素的排序,它僅僅保持插入順序,所以本文給大家介紹了Java 8 如何對 LinkedHashSet 元素進行排序,需要的朋友可以參考下2024-11-11java中的equals()和toString()方法實例詳解
這篇文章主要介紹了java中的equals()和toString()方法實例詳解的相關資料,這里舉例說明,并附實例代碼,和實現(xiàn)效果圖,需要的朋友可以參考下2016-11-11