Module java.base
Package java.util

Class HashMap<K,V>

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

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

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

HashMap实例有两个影响其性能的参数:初始容量负载因子。容量是哈希表中的桶数,初始容量只是哈希表创建时的容量。负载因子是哈希表允许达到的填充程度的度量。当哈希表中的条目数超过负载因子与当前容量的乘积时,哈希表将被重新哈希(即,内部数据结构将被重建),以便哈希表具有大约两倍数量的桶。

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

如果要在HashMap实例中存储许多映射,使用足够大的容量创建它将使映射比让其根据需要自动重新哈希更有效。请注意,使用具有相同hashCode()的许多键是减慢任何哈希表性能的一种方法。为了减轻影响,当键是Comparable时,此类可能使用键之间的比较顺序来帮助打破平局。

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

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

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

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

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

自 JDK 版本:
1.2
参见:
  • Nested Class Summary

    Nested classes/interfaces declared in class java.util.AbstractMap

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

    Nested classes/interfaces declared in interface java.util.Map

    Map.Entry<K,V>
  • Constructor Summary

    Constructors
    Constructor
    Description
    使用默认初始容量(16)和默认负载因子(0.75)构造一个空的HashMap
    HashMap(int initialCapacity)
    使用指定的初始容量和默认负载因子(0.75)构造一个空的HashMap
    HashMap(int initialCapacity, float loadFactor)
    使用指定的初始容量和负载因子构造一个空的HashMap
    HashMap(Map<? extends K,? extends V> m)
    使用指定Map的相同映射构造一个新的HashMap
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    clear()
    从此映射中删除所有映射。
    clone()
    返回此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),则尝试使用给定的映射函数计算其值,并将其输入到此映射中,除非为null
    V
    computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)
    如果指定键的值存在且非空,则尝试根据键及其当前映射值计算新映射。
    boolean
    如果此映射包含指定键的映射,则返回true
    boolean
    如果此映射将一个或多个键映射到指定值,则返回true
    返回此映射中包含的映射的Set视图。
    V
    get(Object key)
    返回指定键映射到的值,如果此映射不包含键的映射,则返回null
    boolean
    如果此映射不包含键-值映射,则返回true
    Set<K>
    keySet()
    返回此映射中包含的键的Set视图。
    V
    merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction)
    如果指定键尚未与值关联或与null关联,则将其与给定的非空值关联。
    static <K, V> HashMap<K,V>
    newHashMap(int numMappings)
    创建一个新的、空的HashMap,适用于预期数量的映射。
    V
    put(K key, V value)
    将指定键与指定值关联在此映射中。
    void
    putAll(Map<? extends K,? extends V> m)
    从指定映射中复制所有映射到此映射。
    V
    remove(Object key)
    如果存在,则从此映射中删除指定键的映射。
    int
    size()
    返回此映射中键-值映射的数量。
    values()
    返回此映射中包含的值的Collection视图。

    Methods declared in class java.util.AbstractMap

    equals, hashCode, toString

    Methods declared in class java.lang.Object

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

    Methods declared in interface java.util.Map

    equals, forEach, getOrDefault, hashCode, putIfAbsent, remove, replace, replace, replaceAll
  • Constructor Details

    • 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)
      使用与指定Map中的映射相同的映射构造一个新的HashMapHashMap使用默认负载因子(0.75)和足以容纳指定Map中映射的初始容量。
      参数:
      m - 要放置其映射到此映射中的映射
      抛出:
      NullPointerException - 如果指定的映射为null
  • Method Details

    • size

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

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

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

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

      返回null值并不一定表示映射不包含键的映射关系;也可能映射将键明确映射到null。可以使用containsKey操作来区分这两种情况。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      映射函数在计算过程中不应修改此映射。

      此方法将尽最大努力在检测到映射函数在计算过程中修改此映射时抛出ConcurrentModificationException

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

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

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

      重映射函数在计算过程中不应修改此映射。

      此方法将尽最大努力在检测到重映射函数在计算过程中修改此映射时抛出ConcurrentModificationException

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

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

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

      重映射函数在计算过程中不应修改此映射。

      此方法将尽最大努力在检测到重映射函数在计算过程中修改此映射时抛出ConcurrentModificationException

      指定者:
      compute 在接口 Map<K,V>
      参数:
      key - 要关联的指定值的键
      remappingFunction - 用于计算值的重映射函数
      返回:
      与指定键关联的新值,如果没有则返回null
      抛出:
      ConcurrentModificationException - 如果检测到重映射函数在计算过程中修改此映射
    • 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,则删除映射。如果重映射函数本身引发(未经检查的)异常,则重新抛出异常,并且当前映射保持不变。

      重映射函数在计算过程中不应修改此映射。

      此方法将尽最大努力在检测到重映射函数在计算过程中修改此映射时抛出ConcurrentModificationException

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

      public Object clone()
      返回此HashMap实例的浅拷贝:键和值本身不会被克隆。
      覆盖:
      clone 在类 AbstractMap<K,V>
      返回:
      此映射的浅拷贝
      参见:
    • newHashMap

      public static <K, V> HashMap<K,V> newHashMap(int numMappings)
      创建一个新的、空的HashMap,适用于预期的映射数量。返回的map使用默认的负载因子0.75,并且其初始容量通常足够大,以便可以添加预期数量的映射而无需调整map的大小。
      类型参数:
      K - 新map维护的键的类型
      V - 映射值的类型
      参数:
      numMappings - 预期的映射数量
      返回:
      新创建的map
      抛出:
      IllegalArgumentException - 如果numMappings为负数
      自版本:
      19