一、哈希值、哈希函数、哈希冲突
1、哈希值
把任意长度的输入(又叫做预映射, pre-image),通过哈希算法,变换成固定长度的输出,该输出就是哈希值。
2、哈希函数
这种转换是一种压缩映射。也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。
简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
哈希函数每次在相同或相等的对象上应用哈希函数时, 应每次返回相同的哈希码。换句话说, 两个相等的对象必须一致地生成相同的哈希码。
Java中的Hash函数
Java 中所有的对象都有 Hash 方法。
Java中的所有对象都继承 Object 类中定义的 hashCode() 函数的默认实现。 此函数通常通过将对象的内部地址转换为整数来生成哈希码,从而为所有不同的对象生成不同的哈希码。
3、哈希冲突:
当有两个或者两个以上数量的键被分配到哈希表数组的同一个索引上,我们称这些键发生了冲突。
4、解决哈希冲突的方法:
- 开发定址法(线性探测再散列,二次探测再散列,伪随机探测再散列)
- 再哈希法:这种方法是同时构造多个不同的哈希函数: Hi=RH1(key) i=1,2,…,k 。当哈希地址Hi=RH1(key)发生冲突时,再计算Hi=RH2(key)……,直到冲突不再产生。这种方法不易产生聚集,但增加了计算时间
- 链地址法:将所有哈希地址相同的都链接在同一个链表中 ,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。 (hashmap就是用此方法解决冲突的。)
hashmap就是用此方法解决冲突的。
- 建立一个公共溢出区
java中hashmap采用的是链地址法
二、HashMap的内部存储结构:
Node数组+链表或红黑树
Node数组:(Node类是HashMap的一个静态内部类)
//Node是HashMap的内部类
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;//保存map中的key
V value;//保存map中的value
Node<K,V> next;//单向链表
Node(int hash, K key, V value, Node<K,V> next) {//构造器
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
三、数组的容量是2的整数次方的原因
要使HashMap存取高效,尽量减少碰撞,就要把数字尽量的分配均匀。
太长的数组