双列集合接口Map

Map接口

Map 是 Java 集合框架中的一个核心接口,用于表示 键值对(Key-Value Pair) 的集合。Map 接口的实现类包括 HashMap、LinkedHashMap、TreeMap 等

特点

  1. 键值对存储

    • Map 存储的是键值对,每个键(Key)映射到一个值(Value)。
    • 键是唯一的,值可以重复
  2. 允许 null 键和 null 值

    • 大多数 Map 实现类(如 HashMap 和 LinkedHashMap)允许键和值为 null。

    • Java 的 Objects.hashCode(Object o) 方法明确规定:若传入 null,返回 0。这是语言层面的约定,用于统一处理 null 的哈希逻辑

      static final int hash(Object key) {
          int h;
          return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
      }
      
      //null 值的哈希值被定义为 0
      
    • TreeMap 不允许键为 null,但允许值为 null

  3. 无序性

    • Map 不保证键值对的顺序(除了 LinkedHashMap 和 TreeMap)。
    • HashMap 是无序的,LinkedHashMap 维护插入顺序,TreeMap 根据键的自然顺序或指定的比较器排序
  4. 非线程安全

    • Map 的实现类(如 HashMap、LinkedHashMap 和 TreeMap)不是线程安全的

Map接口的常用方法

Map 接口定义了一系列操作键值对的方法,主要包括以下几类

  1. 添加键值对

    • V put(K key, V value):将指定的键值对添加到Map 中。如果键已经存在,则替换旧值并返回旧值;如果键不存在,则返回 null
    • void putAll(Map<? extends K, ? extends V> m):将指定Map 中的所有键值对添加到当前 Map 中。

    2.2 删除键值对

    • V remove(Object key):移除指定键对应的键值对,并返回对应的值。如果键不存在,则返回 null
    • void clear():清空Map中的所有键值对。

    2.3 修改键值对

    • V replace(K key, V value):替换指定键对应的值。如果键不存在,则返回 null。
    • boolean replace(K key, V oldValue, V newValue):仅当指定键的当前值等于 oldValue时,才将其替换为 newValue。

    2.4 查询键值对

    • V get(Object key):返回指定键对应的值。如果键不存在,则返回 null。
    • boolean containsKey(Object key):判断Map 中是否包含指定的键。
    • boolean containsValue(Object value):判断 Map 中是否包含指定的值。
    • boolean isEmpty():判断 Map是否为空。
    • int size():返回 Map 中键值对的数量。

    2.5 遍历键值对

    • Set<K> keySet():返回 Map 中所有键的集合。
    • Collection<V> values():返回 Map 中所有值的集合。
    • Set<Map.Entry<K, V>> entrySet():返回 Map 中所有键值对的集合。

    2.6 其他操作

    • default V getOrDefault(Object key, V defaultValue):返回指定键对应的值,如果键不存在,则返回 defaultValue。
    • default void forEach(BiConsumer<? super K, ? super V> action):对 Map 中的每个键值对执行指定的操作

Map接口的常见实现类

  1. HashMap
    • 基于哈希表实现,键值对无序。
    • 允许键和值为 null。
    • 添加、删除和查询操作的时间复杂度为 O(1)
  2. LinkedHashMap
    • 基于哈希表和链表实现,维护键值对的插入顺序或访问顺序。
    • 允许键和值为 null。
    • 添加、删除和查询操作的时间复杂度为 O(1)
  3. TreeMap
    • 基于红黑树实现,键值对根据键的自然顺序或指定的比较器排序。
    • 不允许键为 null,但允许值为 null。
    • 添加、删除和查询操作的时间复杂度为 O(log n)
  4. Hashtable
    • 基于哈希表实现,键值对无序。
    • 不允许键或值为 null。
    • 线程安全(方法使用 synchronized 修饰)
  5. ConcurrentHashMap
    • 基于分段锁实现,支持高并发的键值对操作。
    • 不允许键或值为 null。
    • 线程安全,性能优于 Hashtable

Map接口中的遍历操作

  1. 遍历键(Key)

    • Set<K> keySet():返回 Map 中所有键的集合

    • 通过 keySet() 方法获取 Map 中所有键的集合,然后遍历键集合

      Map<String, Integer> map = new HashMap<>();
      map.put("Apple", 10);
      map.put("Banana", 20);
      map.put("Cherry", 30);
      
      // 遍历键
      for (String key : map.keySet()) {
          System.out.println("Key: " + key);
      }
      
    • KeySet()方法返回的是个Set类型的单列集合,所以可以使用使用 Iterator

      Iterator<String> iterator = map.keySet().iterator();
      while (iterator.hasNext()) {
          String key = iterator.next();
          System.out.println("Key: " + key);
      }
      

    返回的Set类型的特点

    • Map.keySet() 返回的 Set 集合通常是 Map 实现类的内部类实例,而非通用的 HashSet 或 TreeSet

    • 专用内部类:主流 Map 实现类(如 HashMap、TreeMap)会为 keySet() 方法定义一个内部类(如 HashMap.KeySet),该内部类直接引用 Map 中的键数据,不独立存储键值

    • 对 Map 的修改(如增删键)会实时反映到 keySet() 返回的 Set 中,反之亦然(如通过 Set 删除键会同步修改原始 Map)

    • 返回的 Set 通常不支持 add() 或 addAll() 方法(调用会抛出 UnsupportedOperationException),因为键的添加必须通过 Map.put() 方法完成

    • 可以通过keySet() 进行删除,但不能添加

    • 内部类实现的 Set 避免了创建独立集合的开销,直接依赖 Map 的存储结构,提升了遍历和查询效率

      Map<Object, String> treeMap = new TreeMap<>();
      treeMap.put(1,"1");
      treeMap.put(2,"1");
      treeMap.put(3,"1");
      treeMap.put(-1,"1");
      Set<Object> keyset = treeMap.keySet();
      
      keyset.add(11);	//❌java.lang.UnsupportedOperationException
      keyset.remove(3);//✔
      
  2. 遍历值(Value)

    • Collection<V> values():返回 Map 中所有值的集合

    • 通过 values() 方法获取 Map 中所有值的集合,然后遍历值集合

      // 遍历值
      for (Integer value : map.values()) {
          System.out.println("Value: " + value);
      }
      
    • 使用 Iterator

      Iterator<Integer> iterator = map.values().iterator();
      while (iterator.hasNext()) {
          Integer value = iterator.next();
          System.out.println("Value: " + value);
      }
      

    返回的Collection类型的特点

    • 在 Java 的 Map 接口中,values() 方法返回的 Collection 通常是当前 Map 实现类的内部类实例
    • values() 返回的 Collection 是 Map 内部定义的视图集合
    • 视图集合与原始 Map 数据实时同步。例如,若 Map 中删除某个键值对,values() 返回的集合会立即体现这一变化
    • 部分方法可能不支持(如 add()),调用时会抛出 UnsupportedOperationException,因为视图集合不独立存储数据,仅提供访问接口
    • 与内部的Set一样,不能add可以remove
    • 这个Collection集合中没有listIterator()方法,没有这个迭代器
  3. 遍历键值对(Entry)

    • Set<Map.Entry<K, V>> entrySet():返回 Map 中所有键值对的集合

    • 通过 entrySet() 方法获取 Map 中所有键值对的集合,然后遍历键值对集合

    • 如果使用 keySet() 遍历键,再通过 get(key) 获取值,每次获取值都需要一次查找操作

    • 使用 entrySet() 直接获取键值对,避免了额外的查找操作,性能更高

    • 同样的,使用entrySet()返回的集合可以删除不能添加

      // 遍历键值对
      for (Map.Entry<String, Integer> entry : map.entrySet()) {
          System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
       }
      
    • 使用 Iterator

      Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();
      while (iterator.hasNext()) {
          Map.Entry<String, Integer> entry = iterator.next();
          System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
       }
      

    Map.Entry<K, V> 是 Map 接口的内部接口,表示一个键值对。Map实现类的Node节点实现了该接口,它定义了以下方法

    • K getKey()

    • V getValue()

    • V setValue(V value)

      for (Map.Entry entry :entrySet ) {
          Object key = entry.getKey();
          Object value = entry.getValue();
          entry.setValue(3);
      }
      

返回值特点

  • entrySet() 返回的 Set 是 Map 的一个 视图集合,与底层数据结构(如数组、链表、红黑树)直接关联,而非独立的集合实例
  • 这些内部类不实际存储数据,而是通过引用 Map 的原始数据实现高效遍历和操作,避免内存冗余
  • 调用 add() 方法会抛出 UnsupportedOperationException,因为条目(Entry)必须通过 put(K, V) 方法插入到 Map 中
  • 通过 entrySet() 对条目进行修改(如 setValue())会直接反映到原始 Map 中
  1. 使用 forEach() 方法

    • Java 8 引入了 forEach() 方法,可以更简洁地遍历 Map

    • 遍历键值对

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

      map.keySet().forEach(key -> {
          System.out.println("Key: " + key);
      });
      
    • 遍历值

      map.values().forEach(value -> {
          System.out.println("Value: " + value);
      });
      
posted @   QAQ001  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示