抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

1.同步性

HashTable是同步的,线程安全的。
里面所有的方法,isEmpty(),isSize(),contains(),get()方法都加了synchronized关键字进项同步。所以效率很低。
image-20210317065149214

image-20210317065210630

image-20210317065256950

image-20210317065312654

image-20210317065413344

HashMap是线程不安全的。所以效率高。

综合效率和安全,所以我们通常亏考虑oncurrentHashMap,不会把整个方法全部锁住,会采用分段锁的方式。进项数据的锁定。

2.继承的父类不同。

回答面试官的时候,可以说看过,知道他们继承了不同的父类,是什么父类忘了。

HashTable继承了Distionary.

image-20210317065722144

HashMap继承了AbstractMap.

image-20210317065733070

3.对于Null Key和Null Value的支持不同

针对put方法而言的。

HashTable,的value会有非空判断。key如果是空也会报空指针。
image-20210317071845252

HashMap允许为空,判断key为null的时候,就将hash值之设为0。不为null就计算实际的hash。
image-20210317072053362

image-20210317072118957

4.遍历方法不同:

Hashtable、HashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式 。

HashTable
image-20210317072831618

迭代器都是先判断有没有下一个。取出下一个。image-20210317072852752

5. 内部实现使用的数组初始化和扩容方式不同

内部初始化:

HashTable默认初始化使用11.在调用构造方法的时候就初始化了数组。
image-20210317073326706

image-20210317074247264

HashMap构造方法不会进行初始化。初始化值为16。

第一次调用put的时候,才会开辟出数组,进行存储。
image-20210317074628370

重新扩充的方法里
image-20210317074723405

进行初始化构建数组。
image-20210327103609434

扩容:

HashMap

扩容是原来的两倍。HashMap处处体现考虑了效率,使用位运算比x2快。2是整数,需要转换为二进制才能运算,转换的过程耗费资源。
image-20210317075251602

HashTable
image-20210317075925666

image-20210317080036314

2倍+1.

image-20210317080133623
image-20210317080100750

6.计算hash值和下标的方法不同

HashMap

如果key是null则哈希值为0,如果不为0,是字符串的hash方法,是对象是对象本身的hash方法,计算出一个值,高16位向低16位右移,右移16位,高位和爹日同时参数与异或运算,计算出一个新的hash值。为什么右移16位,是int值,int是32位,使得高位参与运算,避免某些hash值计算结果频繁出现在高位。使得分布均匀。
image-20210317082254267

image-20210317082120377

下标的计算:

容量减一参与下标计算。与当前的hash进行与运算。
image-20210317083951311

所以HashMap容量必须保证是2的次幂。
初始化构造方法的时候使用tableSizeFor。

image-20210317091718342

初始化容量可以填任意一个参数。都能够算出离得最近的2的次幂。
image-20210317092423487

HashTable
image-20210317082226180

下标的计算:
将hash的符号位舍去(hash & 0x7FFFFFFF),取余数.其实int就是32位最大容量-1。
image-20210317082720295

HashTable和HashMap理念上就是保留部分hash值的方法。

评论