JAVA的Map集合

在 Java 中,Map 是一种存储键值对(Key-Value)的集合接口,它不继承自 Collection 接口。Map 的核心特点是键的唯一性,每个键最多映射一个值。以下是关于 Map 的详细介绍:

一、核心特性

  1. 键唯一性:键不能重复,重复插入会覆盖原有值(通过 equals() 判断键是否相同)。
  2. 键值关联:每个键映射到一个值,可通过键快速查找对应值。
  3. 无序性:默认不保证元素顺序(如 HashMap),但部分实现(如 LinkedHashMap)可保持插入顺序或访问顺序。

二、常见实现类

1. HashMap
  • 特性:基于哈希表实现,无序,允许 null 键和 null 值(键最多一个 null)。
  • 时间复杂度:插入、删除、查找操作均为 O (1)。
  • 示例

    java

    Map<String, Integer> map = new HashMap<>();
    map.put("apple", 1);
    map.put("banana", 2);
    map.put("apple", 3); // 键重复,覆盖原值
    System.out.println(map); // 输出: {apple=3, banana=2}
    
2. LinkedHashMap
  • 特性:继承自 HashMap,维护双向链表记录插入顺序或访问顺序(通过构造参数指定)。
  • 时间复杂度:基本操作 O (1),但维护顺序会增加开销。
  • 示例(插入顺序)

    java

    Map<String, Integer> map = new LinkedHashMap<>();
    map.put("apple", 1);
    map.put("banana", 2);
    map.put("cherry", 3);
    System.out.println(map); // 输出: {apple=1, banana=2, cherry=3}
    
3. TreeMap
  • 特性:基于红黑树实现,键按自然顺序或指定比较器排序,不允许 null 键。
  • 时间复杂度:插入、删除、查找操作均为 O (log n)。
  • 示例

    java

    Map<Integer, String> map = new TreeMap<>();
    map.put(3, "C");
    map.put(1, "A");
    map.put(2, "B");
    System.out.println(map); // 输出: {1=A, 2=B, 3=C}
    
4. Hashtable
  • 特性:线程安全(所有方法同步),不允许 null 键或值,性能较低。
  • 替代方案:优先使用 ConcurrentHashMap(线程安全且性能更高)。

三、基本操作

1. 添加 / 更新键值对

java

map.put("key", 100); // 返回旧值(若存在),否则返回null
map.putIfAbsent("key", 200); // 仅当键不存在时添加
2. 获取值

java

int value = map.get("key"); // 返回值,若键不存在则返回null(可能NPE)
int defaultValue = map.getOrDefault("key", 0); // 不存在时返回默认值
3. 删除键值对

java

map.remove("key"); // 返回被删除的值,若键不存在返回null
map.remove("key", 100); // 仅当键对应值为100时删除,返回boolean
4. 判断键 / 值存在

java

boolean hasKey = map.containsKey("key");
boolean hasValue = map.containsValue(100);
5. 集合大小

java

int size = map.size();
boolean isEmpty = map.isEmpty();

四、遍历方式

1. 遍历键(keySet)

java

for (String key : map.keySet()) {
    System.out.println("Key: " + key + ", Value: " + map.get(key));
}
2. 遍历值(values)

java

for (int value : map.values()) {
    System.out.println("Value: " + value);
}
3. 遍历键值对(entrySet)

效率最高,避免多次查找:

java

for (Map.Entry<String, Integer> entry : map.entrySet()) {
    System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}
4. Java 8+ forEach()

java

map.forEach((key, value) -> {
    System.out.println("Key: " + key + ", Value: " + value);
});

五、常用方法

1. 合并操作

java

map.merge("key", 1, (oldValue, newValue) -> oldValue + newValue);
// 若键不存在,插入(key, 1);若存在,则将原值与1相加后更新
2. 计算操作

java

map.compute("key", (k, v) -> (v == null) ? 1 : v + 1);
// 若键不存在,插入(key, 1);若存在,则将原值加1
3. 批量操作

java

Map<String, Integer> anotherMap = new HashMap<>();
map.putAll(anotherMap); // 将anotherMap的所有键值对添加到map
map.clear(); // 清空map

六、线程安全

  1. Hashtable:所有方法同步,性能低。
  2. Collections.synchronizedMap():包装非线程安全的 Map

    java

    Map<String, Integer> synchronizedMap = Collections.synchronizedMap(new HashMap<>());
    
  3. ConcurrentHashMap:推荐方案,分段锁实现高效并发:

    java

    Map<String, Integer> concurrentMap = new ConcurrentHashMap<>();
    

七、示例代码

java

import java.util.*;

public class MapExample {
    public static void main(String[] args) {
        // HashMap示例
        Map<String, Integer> fruitPrices = new HashMap<>();
        fruitPrices.put("apple", 5);
        fruitPrices.put("banana", 3);
        fruitPrices.put("apple", 6); // 覆盖原值
        System.out.println("HashMap: " + fruitPrices); // {apple=6, banana=3}
        
        // TreeMap示例(排序)
        Map<Integer, String> numbers = new TreeMap<>();
        numbers.put(3, "Three");
        numbers.put(1, "One");
        numbers.put(2, "Two");
        System.out.println("TreeMap: " + numbers); // {1=One, 2=Two, 3=Three}
        
        // 遍历方式
        System.out.println("\n遍历entrySet:");
        for (Map.Entry<String, Integer> entry : fruitPrices.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
        
        // Java 8+ forEach
        System.out.println("\nJava 8 forEach:");
        fruitPrices.forEach((k, v) -> System.out.println(k + ": " + v));
        
        // 合并操作
        fruitPrices.merge("apple", 2, Integer::sum);
        System.out.println("\n合并后: " + fruitPrices); // {apple=8, banana=3}
    }
}

八、适用场景

  • 缓存:通过键快速查找值。
  • 统计频率:键为元素,值为出现次数。
  • 配置管理:存储键值对配置信息。

选择 Map 实现类时,需根据是否需要排序、保持顺序、线程安全以及性能要求来决定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值