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的链表中。
标签:map,HashMap,bucket,链表,键值,哈希 From: https://www.cnblogs.com/kandh/p/17868055.html