跳转到内容

Java Map接口

来自代码酷

模板:Java集合框架导航

Java Map接口[编辑 | 编辑源代码]

Map接口是Java集合框架中用于存储键值对(key-value pairs)的核心接口,它表示一组唯一的键到值的映射关系。与Collection接口不同,Map不继承自Collection,而是自成体系的独立接口。

基本特性[编辑 | 编辑源代码]

  • 键唯一性:每个键最多映射一个值(不允许重复键)
  • 无序性:大多数实现不保证元素的顺序(LinkedHashMap除外)
  • 允许null值:HashMap和LinkedHashMap允许一个null键和多个null值
  • 非线程安全:基础实现不是线程安全的(可使用Collections.synchronizedMap包装)

核心实现类[编辑 | 编辑源代码]

Java提供了多个Map接口的实现类,主要区别在于:

  • HashMap:基于哈希表的实现(最常用)
  • LinkedHashMap:保持插入顺序或访问顺序
  • TreeMap:基于红黑树,按键的自然顺序或Comparator排序
  • Hashtable:线程安全的遗留类(不推荐新代码使用)
  • ConcurrentHashMap:线程安全的高性能实现

classDiagram Map <|-- HashMap Map <|-- LinkedHashMap Map <|-- TreeMap Map <|-- Hashtable Map <|-- ConcurrentHashMap class Map { <<interface>> +put(K key, V value) +get(Object key) +remove(Object key) +keySet() +values() +entrySet() }

常用方法[编辑 | 编辑源代码]

以下是Map接口的核心方法:

方法签名 描述
V put(K key, V value) 添加键值对,返回旧值(如无则返回null)
V get(Object key) 获取指定键对应的值
V remove(Object key) 删除指定键的映射
boolean containsKey(Object key) 检查是否包含指定键
boolean containsValue(Object value) 检查是否包含指定值
Set<K> keySet() 返回所有键的Set视图
Collection<V> values() 返回所有值的Collection视图
Set<Map.Entry<K,V>> entrySet() 返回所有键值对的Set视图

基础示例[编辑 | 编辑源代码]

以下示例展示HashMap的基本操作:

import java.util.HashMap;
import java.util.Map;

public class MapExample {
    public static void main(String[] args) {
        // 创建Map
        Map<String, Integer> ageMap = new HashMap<>();
        
        // 添加元素
        ageMap.put("Alice", 25);
        ageMap.put("Bob", 30);
        ageMap.put("Charlie", 28);
        
        // 获取元素
        System.out.println("Alice's age: " + ageMap.get("Alice")); // 输出: 25
        
        // 遍历键值对
        for (Map.Entry<String, Integer> entry : ageMap.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
        
        // 检查键是否存在
        System.out.println("Contains key 'Bob': " + ageMap.containsKey("Bob")); // 输出: true
    }
}

输出:

Alice's age: 25
Alice: 25
Bob: 30
Charlie: 28
Contains key 'Bob': true

实现类比较[编辑 | 编辑源代码]

特性 HashMap LinkedHashMap TreeMap Hashtable ConcurrentHashMap
无 | 插入/访问顺序 | 键排序 | 无 | 无
允许 | 允许 | 不允许(如使用自然排序) | 不允许 | 不允许
否 | 否 | 否 | 是 | 是
O(1)平均 | O(1)平均 | O(log n) | O(1)平均 | O(1)平均

实际应用案例[编辑 | 编辑源代码]

场景:统计文本中单词出现的频率

import java.util.HashMap;
import java.util.Map;

public class WordFrequencyCounter {
    public static void main(String[] args) {
        String text = "hello world hello java world map";
        String[] words = text.split(" ");
        
        Map<String, Integer> frequencyMap = new HashMap<>();
        
        for (String word : words) {
            frequencyMap.merge(word, 1, Integer::sum);
        }
        
        System.out.println(frequencyMap);
    }
}

输出:

{world=2, java=1, map=1, hello=2}

高级特性[编辑 | 编辑源代码]

视图集合[编辑 | 编辑源代码]

Map提供三种集合视图:

  • keySet():所有键的Set视图
  • values():所有值的Collection视图
  • entrySet():所有键值对的Set视图(最常用遍历方式)

Java 8新增方法[编辑 | 编辑源代码]

  • getOrDefault():安全获取值
  • putIfAbsent():不存在时才放入
  • compute()/computeIfPresent()/computeIfAbsent():条件计算
  • merge():合并值(如上例所示)
  • forEach():简化遍历

示例:

Map<String, Integer> map = new HashMap<>();
map.put("a", 1);

// Java 8方法示例
System.out.println(map.getOrDefault("b", 0)); // 输出: 0
map.putIfAbsent("a", 100); // 不会替换现有值
map.compute("a", (k, v) -> v + 10); // a的值变为11
map.forEach((k, v) -> System.out.println(k + " -> " + v));

性能考虑[编辑 | 编辑源代码]

  • 初始容量:HashMap默认初始容量为16,负载因子0.75
  • 扩容代价:当元素数量达到(容量×负载因子)时自动扩容
  • 优化建议:预估大小时指定初始容量避免频繁扩容
  • 线程安全选择
 * 单线程:HashMap
 * 高并发读:ConcurrentHashMap
 * 遗留系统:Hashtable

常见问题[编辑 | 编辑源代码]

Q: HashMap和Hashtable的主要区别?

  • HashMap非线程安全,允许null键值;Hashtable线程安全,不允许null键值

Q: 如何选择Map实现?

  • 需要快速访问:HashMap
  • 需要保持插入顺序:LinkedHashMap
  • 需要排序:TreeMap
  • 需要线程安全:ConcurrentHashMap

Q: 为什么Map不继承Collection接口?

  • 因为Map表示键值对集合,而Collection表示单元素集合,语义不同

总结[编辑 | 编辑源代码]

Java Map接口提供了强大的键值对存储能力,是日常开发中最常用的数据结构之一。理解不同实现类的特性及适用场景,能够帮助开发者编写更高效的代码。对于现代Java开发,建议优先使用HashMap(单线程)或ConcurrentHashMap(多线程),并充分利用Java 8引入的新方法简化代码。

模板:Java集合框架导航