哈希表
哈希表(HashTable),也叫散列表,是根据键值对(Key Value)而直接进行访问的数据结构。也就是说,它通过把键值对映射到表中一个位置来访问记录,以加快查找的速度。哈希表主要是通过哈希函数将键映射为表中的一个位置,然后在该位置存储值。哈希表在实现上采用了数组和链表相结合的数据结构。
Java中的哈希表是通过HashMap类来实现的,它也是Java中最常用的数据结构之一。
HashMap类
创建一个HashMap对象
可以使用以下语法创建一个HashMap对象:
HashMap<String, Integer> hashMap = new HashMap<String, Integer>();
其中,String和Integer分别代表键和值的类型。也可以使用Diamond语法来创建HashMap对象
如下所示:
HashMap<String, Integer> hashMap = new HashMap<>();
添加元素
可以使用put()方法向HashMap中添加元素,如下所示:
hashMap.put("apple", 1);
hashMap.put("banana", 2);
hashMap.put("orange", 3);
其中,第一个参数代表键,第二个参数代表值。如果键已经存在,则会将该键对应的值替换为新的值。
获取元素
可以使用get()方法从HashMap中获取元素
如下所示:
Integer value = hashMap.get("apple");
其中,get()方法的参数是键,返回值是对应的值。如果指定的键不存在,则返回null。
删除元素
可以使用remove()方法从HashMap中删除元素
如下所示:
hashMap.remove("apple");
其中,remove()方法的参数是要删除的键。
遍历元素
可以使用以下方法来遍历HashMap中的元素:
for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + ": " + value);
}
其中,entrySet()方法返回一个Set集合,该集合包含了所有的键值对。对于每个键值对,可以通过getKey()和getValue()方法来获取对应的键和值。
哈希冲突
在使用哈希表时,可能会出现哈希冲突的情况。哈希冲突是指不同的键经过哈希函数后映射到了相同的位置。为了解决哈希冲突,HashMap采用了链表来存储值。当发生哈希冲突时,新的值会被插入到链表的头部。当链表的长度超过一定阈值时,链表就会被转换为红黑树,以提高查找的速度。
哈希表的性能
哈希表的性能取决于哈希函数的质量,哈希表的大小和存储密度。以下是哈希表的性能方面需要注意的几个点:
- 哈希函数的选择:好的哈希函数可以减少哈希冲突,从而提高哈希表的性能。常见的哈希函数包括直接取模法、乘法哈希法、一致性哈希等。
- 哈希表的大小:哈希表的大小会直接影响哈希冲突的概率。哈希表大小通常选择为质数,可以减少哈希冲突的概率。
- 存储密度:存储密度指的是哈希表中实际存储的元素数量与哈希表大小的比值。存储密度过高或过低都会影响哈希表的性能。通常来说,存储密度应该控制在0.7左右。
- 冲突解决策略:哈希表中元素哈希冲突时,需要进行冲突解决。常见的冲突解决策略包括拉链法和开放定址法。拉链法需要使用链表来存储哈希冲突的元素,开放定址法则是在哈希表中寻找其他空闲的位置来存储冲突的元素。
- 哈希表的扩容:当哈希表中存储的元素过多时,需要扩容来减少哈希冲突的概率。哈希表的扩容通常是先创建一个更大的哈希表,然后将原哈希表中的元素重新哈希到新哈希表中。哈希表扩容时会带来性能损失,但可以保证哈希表的性能稳定性。