原文: https://howtodoinjava.com/java-hashmap/

Java 中的HashMap在实现Map接口的集合类中。 它用于存储键值对。 每个键都映射到映射中的单个值。

键是唯一的。 这意味着我们只能在映射中插入键K一次。 不允许重复的键。 虽然值V可以映射到多个键。

1. java.util.HashMap

1.1 HashMap类声明

HashMap已声明如下:

  1. public class HashMap<K,V> extends AbstractMap<K,V>
  2. implements Map<K,V>, Cloneable, Serializable

1.2 HashMap类层次结构

如上所示,HashMap实现Map接口并扩展AbstractMap类。

Java `HashMap`指南 - 图1

HashMap层次结构

2. Java HashMap特性

  • HashMap不能包含重复的键。
  • HashMap允许多个null值,但只允许一个null键。
  • HashMap无序集合。 它不保证元素的任何特定顺序。
  • HashMap不是线程安全的。 您必须显式同步对HashMap的并发修改。 或者,您可以使用Collections.synchronizedMap(hashMap)来获取HashMap的同步版本。
  • 只能使用关联的键来检索值。
  • HashMap仅存储对象引用。 因此,必须将原始类型与其对应的包装器类一起使用。 例如int将存储为Integer
  • HashMap实现了Clonableserializable接口。

3. HashMap内部实现

HashMap按照哈希原理工作。 在将任何公式/算法应用于其属性之后,哈希是一种为任何变量/对象分配唯一代码的方法。 Java 中的每个对象都有其哈希码,这样两个相等的对象必须一致地产生相同的哈希码。

3.1 HashMap.Entry

键值对存储为内部类HashMap.Entry的实例,该内部类将键和值映射存储为属性。 键已标记为final

  1. static class Entry<K ,V> implements Map.Entry<K, V>
  2. {
  3. final K key;
  4. V value;
  5. Entry<K ,V> next;
  6. final int hash;
  7. ...//More code goes here
  8. }

3.2 内部工作

Entry类的所有实例都存储在声明为transient Entry[] table的数组中。 对于要存储在HashMap中的每个键值,使用键的哈希码计算哈希值。 该哈希值用于计算数组中用于存储Entry对象的索引

冲突的情况下,其中多个键映射到单个索引位置,形成的链表用来存储所有应该放在单个数组索引位置的所有键值对。

通过键检索值时,使用键的哈希码可以找到第一个索引位置。 然后,在链表中迭代所有元素,并使用equals()方法识别正确的键,从而找到正确的值对象。

4. Java HashMap示例

让我们快速浏览一些示例,以在 Java 中使用HashMap

4.1 添加键值 – HashMap.put()

  1. import java.util.HashMap;
  2. public class HashMapExample
  3. {
  4. public static void main(String[] args) throws CloneNotSupportedException
  5. {
  6. HashMap<Integer, String> map = new HashMap<>();
  7. map.put(1, "A");
  8. map.put(2, "B");
  9. map.put(3, "C");
  10. System.out.println(map);
  11. }
  12. }

程序输出。

  1. {1=A, 2=B, 3=C}

4.2 通过键获取值 – HashMap.get()

  1. HashMap<Integer, String> map = new HashMap<>();
  2. map.put(1, "A");
  3. map.put(2, "B");
  4. map.put(3, "C");
  5. String value = map.get(2);
  6. System.out.println("The value is :: "+ value );

程序输出:

  1. The value is :: B

4.3 通过键删除偶对 – HashMap.remove()

  1. HashMap<Integer, String> map = new HashMap<>();
  2. map.put(1, "A");
  3. map.put(2, "B");
  4. map.put(3, "C");
  5. System.out.println(map);
  6. map.remove(3);
  7. System.out.println(map);

程序输出:

  1. {1=A, 2=B, 3=C}
  2. {1=A, 2=B}

4.4 迭代HashMap

请注意,此类的迭代器为快速失败,如果在创建迭代器后进行了任何结构修改,它将抛出ConcurrentModificationException

  1. HashMap<Integer, String> map = new HashMap<>();
  2. map.put(1, "A");
  3. map.put(2, "B");
  4. map.put(3, "C");
  5. System.out.println("//Iterate over keys");
  6. Iterator<Integer> itr = map.keySet().iterator();
  7. while (itr.hasNext())
  8. {
  9. Integer key = itr.next();
  10. String value = map.get(key);
  11. System.out.println("The key is :: " + key + ", and value is :: " + value );
  12. }
  13. System.out.println("//Iterate over entries set");
  14. Iterator<Entry<Integer, String>> entryIterator = map.entrySet().iterator();
  15. while (entryIterator.hasNext())
  16. {
  17. Entry<Integer, String> entry = entryIterator.next();
  18. System.out.println("The key is :: " + entry.getKey() + ", and value is :: " + entry.getValue() );
  19. }

程序输出:

//Iterate over keys
The key is :: 1, and value is :: A
The key is :: 2, and value is :: B
The key is :: 3, and value is :: C

//Iterate over entries set
The key is :: 1, and value is :: A
The key is :: 2, and value is :: B
The key is :: 3, and value is :: C

5. HashMap方法

HashMap 类中的方法列表及其简短描述。

  1. void clear():从HashMap中删除所有键值对。
  2. Object clone():返回指定HashMap的浅表副本。
  3. boolean containsKey(Key key):根据是否在映射中找到指定的键,返回truefalse
  4. boolean containsValue(Value Value):类似于containsKey()方法,它查找指定的值而不是键。
  5. Value get(Key key):返回HashMap中指定键的值。
  6. boolean isEmpty():检查映射是否为空。
  7. Set keySet():返回HashMap中存储的所有键的Set
  8. Object put(Key k, Value v):将键值对插入HashMap中。
  9. int size():返回映射的大小,该大小等于存储在HashMap中的键值对的数量。
  10. Collection values():返回映射中所有值的集合。
  11. Value remove(Key key):移除指定键的键值对。
  12. void putAll(Map m):将映射的所有元素复制到另一个指定的映射。

6. HashMap 教程和示例

学习愉快!