HashMap

发布时间 2023-11-30 19:09:33作者: kandhera

HashMap是一种非常重要的数据结构,它实现了Map接口,允许我们存储和检索键值对。HashMap使用哈希表作为其内部实现,通过哈希码来定位键值对。

HashMap的内部实现

数据结构:HashMap内部使用一个数组实现,每个数组元素称为一个bucket。在默认情况下,HashMap的bucket大小为16。每个bucket可以包含一个链表,链表中的每个节点都包含一个键值对。当存储一个键值对时,HashMap会根据键的哈希码计算出  对应的bucket索引,然后将键值对存储在该bucket的链表中。

哈希冲突:由于哈希表的特性,不同的键可能会计算出相同的bucket索引,从而导致哈希冲突。HashMap使用链表来解决哈希冲突。当发生哈希冲突时,新的键值对会被添加到与该bucket对应的链表的末尾。如果链表长度超过一定阈值(默认为8),链表会转化为红黑树,从而提高查询效率。

动态扩容:随着键值对的不断增加,HashMap需要动态扩容以容纳更多的数据。扩容会导致HashMap重新计算所有键的哈希码,并将键值对重新存储到新的bucket中。这个过程是比较耗时的,因此当HashMap达到一定的容量时,最好提前进行扩容。

代码实现:

要创建HashMap对象,我们需要使用HashMap类,并传入一个初始化大小参数来指定bucket的数量。

Map<String, Integer> map = new HashMap<>(16);

添加键值对:

map.put("apple", 1);  
map.put("banana", 2);  
map.put("orange", 3);

获取值:

int value = map.get("apple"); // value = 1

遍历Map:

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

还可以使用keySet()方法来遍历所有的键,或者使用values()方法来遍历所有的值。

for (String key : map.keySet()) {  
    System.out.println(key + " : " + map.get(key));  
}

HashMap允许使用null作为键和值。但是需要注意的是,如果使用null作为键,那么在计算哈希码时会直接使用key的hashCode()方法,而不是通过将key与一个固定的对象进行比较来计算哈希码。因此,如果使用null作为键,需要特别注意避免哈希冲突的问题。另外,如果使用null作为值,那么在获取value时可能会得到null。

总结:

HashMap是Java中常用的数据结构之一,它基于哈希表实现,允许我们存储和检索键值对。HashMap内部使用一个数组实现,每个数组元素称为一个bucket。在默认情况下,HashMap的bucket大小为16。每个bucket可以包含一个链表,链表中的每个节点都包含一个键值对。当存储一个键值对时,HashMap会根据键的哈希码计算出对应的bucket索引,然后将键值对存储在该bucket的链表中。