HashTable
哈希表(散列表),思想是利用散列函数f(x),把关键字k映射到f(k)地址空间,在该地址空间中得到关键字k对应的值。这样就不需要比对,直接定位找到要找的值。
1)碰撞:如果不同的关键字k1和k2,映射到了相同的地址空间,则称为碰撞;
2)均匀散列函数:如果对于任意关键字k,其映射到地址集合中的任意地址的概率相等,则称该映射函数为均匀散列函数;
3)几种常用散列函数:i.除留余数,例如对整型的key除以8求余数,对应一个8位的数组,数组中每一位再加一个链表处理碰撞;
ii.线性地址,直接取关键字的某个线性函数作为散列函数;
iii.平方折中,如果不知道各元素出现的频率如何,可以对元素内部编码平方后取中间值作为散列值,因为中间值与各个位上的元素都有关;
iiii.数学统计分析,考察各元素中相对较为随机的部分作为散列函数
HashMap
基于HashTable实现的Map接口,与HashTable有两点不同:
1)允许null作为key和value,而在哈希表中不允许;
2)非同步,即多线程环境下,某一线程对HashMap造成的结构上的改变,如增添、删除一个或多个映射关系时,其他线程并不能获得该改变结果,所以hashmap是线程非安全的,而hashtable是线程安全的;
hashmap不允许存放相同的关键字,hashset不允许存放相同的对象;
附
Hashcode
object类包含hashcode()和equals()方法,其中hashcode是根据对象的地址计算得到的,计算结果对应于数组下标,用于快速查询;equals方法比较的是两个对象的地址,因此即使是同一个类创建的不同对象,用equals方法比较,返回值也是false;
如果要重载equals方法,就一定要重载hashcode方法,因为equals判断相等是两个对象的hashcode相等的充分不必要条件,判断两个对象是否equals,会对其hashcode做比较,因此一定要重载hashcode方法;
equals和==
==比较的是两个对象的引用是否相等,即比较栈中的内容。即使是同一个类创建的不同对象,用==比较结果也一定为false,因为两个对象的引用不同。
基类object中,equals方法就是用==实现的,因此调用该方法,得到结果与==一致;而在String类、Integer类、Double类等等中对equals实现了重载(当然一定也对hashcode实现了重载),当引用不同时(即栈中内容不同时),还去比较对象的内容(即比较堆中的内容),如果内容相同,还是返回true;前面说一定对hashcode实现了重载,原因在于,如果不重载,hashcode仍然计算对象地址的散列值,不同对象的结果必然仍是不同的,如果两个对象的hashcode不同,则equals一定不同,那么equals重载就失去了效果。