模块 java.base
 java.util

类 HashMap<K,V>

java.lang.Object
java.util.AbstractMap <K,V>
java.util.HashMap<K,V>
类型参数:
K - 此map维护的键类型
V - 映射值的类型
所有已实现的接口:
Serializable , Cloneable , Map<K,V>
已知子类:
LinkedHashMap , PrinterStateReasons

public class HashMap<K,V> extends AbstractMap <K,V> implements Map <K,V>, Cloneable , Serializable
Map 接口的基于哈希表的实现。此实现提供所有可选的map操作,并允许 null 值和 null 键。 ( HashMap 类大致等同于 Hashtable ,只是它是非同步的并且允许空值。)此类不保证映射的顺序;特别是,它不保证顺序会随着时间的推移保持不变。

此实现为基本操作(getput)提供恒定时间性能,假设散列函数将元素适当地分散在桶中。迭代集合视图需要的时间与 HashMap 实例的“容量”(桶的数量)加上它的大小(键值映射的数量)成正比。因此,如果迭代性能很重要,则不要将初始容量设置得太高(或负载因子太低)。

HashMap 的实例有两个影响其性能的参数:初始容量负载系数.这capacity是哈希表中桶的数量,初始容量就是创建哈希表时的容量。这负载系数是哈希表在其容量自动增加之前允许达到多满的量度。当哈希表中的条目数超过负载因子与当前容量的乘积时,哈希表为重新散列(即重建内部数据结构)使得哈希表的桶数大约是原来的两倍。

作为一般规则,默认加载因子 (.75) 提供了时间和空间成本之间的良好折衷。较高的值会减少空间开销,但会增加查找成本(反映在 HashMap 类的大多数操作中,包括 getput )。在设置其初始容量时应考虑map中预期的条目数及其负载因子,以尽量减少重新哈希操作的次数。如果初始容量大于最大条目数除以负载因子,则不会发生重新散列操作。

如果要在 HashMap 实例中存储许多映射,则创建具有足够大容量的映射将使映射的存储比让它根据需要执行自动重新散列以扩大表更有效。请注意,使用具有相同 hashCode() 的许多键肯定会降低任何哈希表的性能。为了改善影响,当键为 Comparable 时,此类可以使用键之间的比较顺序来帮助打破关系。

请注意,此实现不是同步的。 如果多个线程同时访问hash map,并且至少有一个线程在结构上修改了map,则它必须外部同步。 (结构修改是添加或删除一个或多个映射的任何操作;仅更改与实例已包含的键关联的值不是结构修改。)这通常是通过同步某些自然封装映射的对象来实现的.如果不存在这样的对象,则应使用 Collections.synchronizedMap 方法“包装”map。这最好在创建时完成,以防止意外的不同步访问map:

  Map m = Collections.synchronizedMap(new HashMap(...));

此类的所有“集合视图方法”返回的迭代器是快速失败:如果在创建迭代器后的任何时间以任何方式修改map的结构,除了通过迭代器自己的 remove 方法,迭代器将抛出一个 ConcurrentModificationException 。因此,面对并发修改,迭代器会快速干净地失败,而不是冒着在未来不确定的时间出现任意的、不确定的行为的风险。

请注意,无法保证迭代器的快速失败行为,因为一般来说,在存在非同步并发修改的情况下不可能做出任何硬性保证。快速失败迭代器会尽最大努力抛出 ConcurrentModificationException。因此,编写依赖于此异常的正确性的程序是错误的:迭代器的快速失败行为应该只用于检测错误。

此类是 Java 集合框架 的成员。

自从:
1.2
参见:
  • 内部类总结

    在类 java.util.AbstractMap 中声明的嵌套类/接口

    AbstractMap.SimpleEntry<K,V>, AbstractMap.SimpleImmutableEntry<K,V>

    在接口 java.util.Map 中声明的嵌套类/接口

    Map.Entry<K,V>
  • 构造方法总结

    构造方法
    构造方法
    描述
    使用默认初始容量 (16) 和默认负载因子 (0.75) 构造一个空的 HashMap
    HashMap(int initialCapacity)
    构造一个具有指定初始容量和默认加载因子 (0.75) 的空 HashMap
    HashMap(int initialCapacity, float loadFactor)
    构造一个具有指定初始容量和加载因子的空HashMap
    HashMap(Map<? extends K,? extends V> m)
    构造一个新的 HashMap,其映射与指定的 Map 相同。
  • 方法总结

    修饰符和类型
    方法
    描述
    void
    从此map中删除所有映射。
    返回此 HashMap 实例的浅表副本:键和值本身未被克隆。
    V
    compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)
    尝试计算指定键及其当前映射值的映射(如果没有当前映射,则为 null)。
    V
    computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
    如果指定的键尚未与值关联(或映射到 null ),则尝试使用给定的映射函数计算其值并将其输入此map,除非 null
    V
    computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)
    如果指定键的值存在且非空,则尝试在给定键及其当前映射值的情况下计算新映射。
    boolean
    如果此map包含指定键的映射,则返回 true
    boolean
    如果此map将一个或多个键映射到指定值,则返回 true
    返回此map中包含的映射的 Set 视图。
    V
    get(Object key)
    返回指定键映射到的值,如果此map不包含键的映射,则返回 null
    boolean
    如果此map不包含键值映射,则返回 true
    Set<K>
    返回此map中包含的键的 Set 视图。
    V
    merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction)
    如果指定的键尚未与值关联或与 null 关联,则将其与给定的非 null 值关联。
    static <K, V> HashMap<K,V>
    newHashMap(int numMappings)
    创建一个适合预期映射数量的新的空 HashMap。
    V
    put(K key, V value)
    将指定值与此map中的指定键相关联。
    void
    putAll(Map<? extends K,? extends V> m)
    将指定map中的所有值复制到此map。
    V
    remove(Object key)
    从此map中删除指定键的映射(如果存在)。
    int
    size()
    返回此map中键值映射的数量。
    返回此map中包含的值的 Collection 视图。

    在类 java.util.AbstractMap 中声明的方法

    equals, hashCode, toString

    在类 java.lang.Object 中声明的方法

    finalize, getClass, notify, notifyAll, wait, wait, wait

    在接口 java.util.Map 中声明的方法

    equals, forEach, getOrDefault, hashCode, putIfAbsent, remove, replace, replace, replaceAll
  • 构造方法详细信息

    • HashMap

      public HashMap(int initialCapacity, float loadFactor)
      构造一个具有指定初始容量和加载因子的空HashMap
      API 注意:
      要创建初始容量可容纳预期映射数量的 HashMap,请使用 newHashMap
      参数:
      initialCapacity——初始容量
      loadFactor - 负载系数
      抛出:
      IllegalArgumentException - 如果初始容量为负或负载因子为非正
    • HashMap

      public HashMap(int initialCapacity)
      构造一个具有指定初始容量和默认加载因子 (0.75) 的空 HashMap
      API 注意:
      要创建初始容量可容纳预期映射数量的 HashMap,请使用 newHashMap
      参数:
      initialCapacity - 初始容量。
      抛出:
      IllegalArgumentException - 如果初始容量为负。
    • HashMap

      public HashMap()
      使用默认初始容量 (16) 和默认负载因子 (0.75) 构造一个空的 HashMap
    • HashMap

      public HashMap(Map <? extends K ,? extends V > m)
      构造一个新的 HashMap,其映射与指定的 Map 相同。 HashMap 是使用默认加载因子 (0.75) 和足以容纳指定 Map 中的映射的初始容量创建的。
      参数:
      m - 其映射要放置在此map中的map
      抛出:
      NullPointerException - 如果指定的map为空
  • 方法详情

    • size

      public int size()
      返回此map中键值映射的数量。
      指定者:
      size 在接口 Map<K,V>
      重写:
      size 在类 AbstractMap<K,V>
      返回:
      此map中键值映射的数量
    • isEmpty

      public boolean isEmpty()
      如果此map不包含键值映射,则返回 true
      指定者:
      isEmpty 在接口 Map<K,V>
      重写:
      isEmpty 在类 AbstractMap<K,V>
      返回:
      true 如果此map不包含键值映射
    • get

      public V  get(Object  key)
      返回指定键映射到的值,如果此map不包含键的映射,则返回 null

      更正式地说,如果此map包含从键 k 到值 v 的映射,使得 (key==null ? k==null : key.equals(k)) ,则此方法返回 v ;否则返回 null 。 (最多可以有一个这样的映射。)

      null 的返回值不一定指示映射不包含键的映射;map也可能将密钥显式映射到 nullcontainsKey 操作可用于区分这两种情况。

      指定者:
      get 在接口 Map<K,V>
      重写:
      get 在类 AbstractMap<K,V>
      参数:
      key - 要返回其关联值的键
      返回:
      指定键映射到的值,如果此map不包含键的映射,则返回 null
      参见:
    • containsKey

      public boolean containsKey(Object  key)
      如果此map包含指定键的映射,则返回 true
      指定者:
      containsKey 在接口 Map<K,V>
      重写:
      containsKey 在类 AbstractMap<K,V>
      参数:
      key - 要测试其在此map中是否存在的密钥
      返回:
      true 如果此map包含指定键的映射。
    • put

      public V  put(K  key, V  value)
      将指定值与此map中的指定键相关联。如果map之前包含键的映射,则旧值将被替换。
      指定者:
      put 在接口 Map<K,V>
      重写:
      put 在类 AbstractMap<K,V>
      参数:
      key - 与指定值关联的键
      value - 与指定键关联的值
      返回:
      key 关联的先前值,如果没有 key 的映射,则为 null 。 (返回 null 还可以指示之前将 nullkey 相关联的映射。)
    • putAll

      public void putAll(Map <? extends K ,? extends V > m)
      将指定map中的所有映射复制到此map。这些映射将替换此map对指定map中当前任何键的任何映射。
      指定者:
      putAll 在接口 Map<K,V>
      重写:
      putAll 在类 AbstractMap<K,V>
      参数:
      m - 要存储在此map中的映射
      抛出:
      NullPointerException - 如果指定的map为空
    • remove

      public V  remove(Object  key)
      从此map中删除指定键的映射(如果存在)。
      指定者:
      remove 在接口 Map<K,V>
      重写:
      remove 在类 AbstractMap<K,V>
      参数:
      key - 要从map中删除其映射的键
      返回:
      key 关联的先前值,如果没有 key 的映射,则为 null 。 (返回 null 还可以指示之前将 nullkey 相关联的映射。)
    • clear

      public void clear()
      从此map中删除所有映射。此调用返回后map将为空。
      指定者:
      clear 在接口 Map<K,V>
      重写:
      clear 在类 AbstractMap<K,V>
    • containsValue

      public boolean containsValue(Object  value)
      如果此map将一个或多个键映射到指定值,则返回 true
      指定者:
      containsValue 在接口 Map<K,V>
      重写:
      containsValue 在类 AbstractMap<K,V>
      参数:
      value - 要测试其在此map中是否存在的值
      返回:
      true 如果此map将一个或多个键映射到指定值
    • keySet

      public Set <K > keySet()
      返回此map中包含的键的 Set 视图。该集合由map支持,因此对map的更改会反映在集合中,反之亦然。如果在对集合进行迭代时修改map(除了通过迭代器自己的 remove 操作),迭代的结果是不确定的。该集合支持元素删除,即通过 Iterator.removeSet.removeremoveAllretainAllclear 操作从map中删除相应的映射。它不支持 addaddAll 操作。
      指定者:
      keySet 在接口 Map<K,V>
      重写:
      keySet 在类 AbstractMap<K,V>
      返回:
      此map中包含的键的集合视图
    • values

      public Collection <V > values()
      返回此map中包含的值的 Collection 视图。集合由map支持,因此对map的更改会反映在集合中,反之亦然。如果在对集合进行迭代时修改map(除了通过迭代器自己的 remove 操作),迭代的结果是不确定的。该集合支持元素删除,即通过 Iterator.removeCollection.removeremoveAllretainAllclear 操作从map中删除相应的映射。它不支持 addaddAll 操作。
      指定者:
      values 在接口 Map<K,V>
      重写:
      values 在类 AbstractMap<K,V>
      返回:
      此map中包含的值的视图
    • entrySet

      public Set <Map.Entry <K ,V >> entrySet()
      返回此map中包含的映射的 Set 视图。该集合由map支持,因此对map的更改会反映在集合中,反之亦然。如果在对集合进行迭代时映射被修改(除了通过迭代器自己的 remove 操作,或通过迭代器返回的映射条目上的 setValue 操作),迭代的结果是未定义的。该集合支持元素移除,即通过 Iterator.removeSet.removeremoveAllretainAllclear 操作从map中移除相应的映射。它不支持 addaddAll 操作。
      指定者:
      entrySet 在接口 Map<K,V>
      返回:
      此map中包含的映射的集合视图
    • computeIfAbsent

      public V  computeIfAbsent(K  key, Function <? super K ,? extends V > mappingFunction)
      如果指定的键尚未与值关联(或映射到 null ),则尝试使用给定的映射函数计算其值并将其输入此map,除非 null

      如果map函数返回 null ,则不记录任何映射。如果map函数本身抛出(未经检查的)异常,则重新抛出异常,并且不记录任何映射。最常见的用法是构造一个新对象作为初始映射值或记忆结果,如下所示:

       
       map.computeIfAbsent(key, k -> new Value(f(k)));
        

      或者实现多值映射 Map<K,Collection<V>> ,支持每个键多个值:

       
       map.computeIfAbsent(key, k -> new HashSet<V>()).add(v);
        

      映射函数不应在计算期间修改此map。

      如果检测到映射函数在计算期间修改此map,则此方法将尽最大努力抛出 ConcurrentModificationException

      指定者:
      computeIfAbsent 在接口 Map<K,V>
      参数:
      key - 与指定值关联的键
      mappingFunction - 计算值的映射函数
      返回:
      与指定键关联的当前(现有或计算)值,如果计算值为 null,则为 null
      抛出:
      ConcurrentModificationException - 如果检测到映射函数修改了这个map
    • computeIfPresent

      public V  computeIfPresent(K  key, BiFunction <? super K ,? super V ,? extends V > remappingFunction)
      如果指定键的值存在且非空,则尝试在给定键及其当前映射值的情况下计算新映射。

      如果重映射函数返回 null ,则删除映射。如果重映射函数本身抛出(未经检查的)异常,则重新抛出异常,并且当前映射保持不变。

      重新映射函数不应在计算期间修改此map。

      如果检测到重新映射函数在计算期间修改了此map,则此方法将尽最大努力抛出 ConcurrentModificationException

      指定者:
      computeIfPresent 在接口 Map<K,V>
      参数:
      key - 与指定值关联的键
      remappingFunction - 计算值的重映射函数
      返回:
      与指定键关联的新值,如果没有则为 null
      抛出:
      ConcurrentModificationException - 如果检测到重映射函数修改了这个map
    • compute

      public V  compute(K  key, BiFunction <? super K ,? super V ,? extends V > remappingFunction)
      尝试计算指定键及其当前映射值的映射(如果没有当前映射,则为 null)。例如,要创建或将 String 消息附加到值映射:
       
       map.compute(key, (k, v) -> (v == null) ? msg : v.concat(msg)) 
      (方法 merge() 通常更易于用于此类目的。)

      如果重新映射函数返回 null ,则映射将被删除(或者如果最初不存在则保持不存在)。如果重映射函数本身抛出(未经检查的)异常,则重新抛出异常,并且当前映射保持不变。

      重新映射函数不应在计算期间修改此map。

      如果检测到重新映射函数在计算期间修改了此map,则此方法将尽最大努力抛出 ConcurrentModificationException

      指定者:
      compute 在接口 Map<K,V>
      参数:
      key - 与指定值关联的键
      remappingFunction - 计算值的重映射函数
      返回:
      与指定键关联的新值,如果没有则为 null
      抛出:
      ConcurrentModificationException - 如果检测到重映射函数修改了这个map
    • merge

      public V  merge(K  key, V  value, BiFunction <? super V ,? super V ,? extends V > remappingFunction)
      如果指定的键尚未与值关联或与 null 关联,则将其与给定的非 null 值关联。否则,将关联值替换为给定重映射函数的结果,或者如果结果为 null 则移除。当组合一个键的多个映射值时,此方法可能有用。例如,要创建 String msg 或将其附加到值映射:
       
       map.merge(key, msg, String::concat)
        

      如果重映射函数返回 null ,则删除映射。如果重映射函数本身抛出(未经检查的)异常,则重新抛出异常,并且当前映射保持不变。

      重新映射函数不应在计算期间修改此map。

      如果检测到重新映射函数在计算期间修改了此map,则此方法将尽最大努力抛出 ConcurrentModificationException

      指定者:
      merge 在接口 Map<K,V>
      参数:
      key - 与结果值关联的键
      value - 要与键关联的现有值合并的非空值,或者,如果没有现有值或空值与键关联,则与键关联
      remappingFunction - 重新映射函数以重新计算值(如果存在)
      返回:
      与指定键关联的新值,如果没有值与该键关联,则返回 null
      抛出:
      ConcurrentModificationException - 如果检测到重映射函数修改了这个map
    • clone

      public Object  clone()
      返回此 HashMap 实例的浅表副本:键和值本身未被克隆。
      重写:
      clone 在类 AbstractMap<K,V>
      返回:
      这张map的浅表副本
      参见:
    • newHashMap

      public static <K, V> HashMap <K,V> newHashMap(int numMappings)
      创建一个适合预期映射数量的新的空 HashMap。返回的map使用默认的加载因子 0.75,它的初始容量通常足够大,因此可以在不调整map大小的情况下添加预期数量的映射。
      类型参数:
      K - 新map维护的键类型
      V - 映射值的类型
      参数:
      numMappings - 预期的映射数
      返回:
      新创建的map
      抛出:
      IllegalArgumentException - 如果 numMappings 为负
      自从:
      19