Java中HashMap与Hashtable的区别

2019-04-23  本文已影响0人  LuciusWang
1、讲这两者之前先讲一讲 ==,equals() 与hashcode()之间的关系

1.1 ==对于java中基本数据类型变量就是比较变量值;对于非基本数据类型类型,比较的是对象在内存中的地址;
1.2 equals()是所有类(所有类都继承自Object)中都含有的一个方法,当没有重写equals()方法时,equals()等价于==也是判断内存地址是否相同,重写的情况下往往用来判断属性是否相同;
1.3 hashcode()也是每个类(Object类中的方法)都有的方法,当不重写该方法时,某些jvm会将内存地址作为返回值。
1.4 因为Java的集合需要存取对象时,是要根据对象的hashcode方法的返回值来确定对象是否相同,所以要保证你的类使用Java集合不出异常的话,我们必须遵循以下规则:
1)当两个对象equals()比较相同时,它们的hashcode()返回值也一定相同;
2)当两个对象hashcode()返回值相同时,它们equals()比较未必相同;
1.5 重写hashcode()方法也很简单,往往通过计算相关字段的哈希码,再把这些哈希码组合起来得到哈希码。
举个例子:

@Override
public int hashcode(){     
    return Objects.hash(firstName, lastName); 
}
2、现在进入正题,来说说HashMap与Hashtable的区别

2.1 HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。
2.2 HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。
2.3 由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。
2.4 HashMap可以通过下面的语句进行同步:
Map m = Collections.synchronizeMap(hashMap);

3、hashmap与hashtable的实现

3.1 初始容量大小和每次扩充容量大小
1)HashMap默认的初始化大小为16。之后每次扩充,容量变为原来的2倍。
2)Hashtable默认的初始大小为n,之后每次扩充,容量变为原来的2n+1;
HashMap的初始大小固定为16,而Hashtable由你给定。
之所以会有这样的不同,是因为Hashtable和HashMap设计时的侧重点不同。Hashtable的侧重点是哈希的结果更加均匀,使得哈希冲突减少。当哈希表的大小为素数时,简单的取模哈希的结果会更加均匀。而HashMap则更加关注hash的计算效率问题。在取模计算时,如果模数是2的幂,那么我们可以直接使用位运算来得到结果,效率要大大高于做除法。HashMap为了加快hash的速度,将哈希表的大小固定为了2的幂。当然这引入了哈希分布不均匀的问题,所以HashMap为解决这问题,又对hash算法做了一些改动。这从而导致了Hashtable和HashMap的计算hash值的方法不同
3.2 计算hash值的方法
1)HashMap计算hash值的方法

int hash = key.hashCode();
int index = hash & map.length();

2)Hashtable计算hash值的方法

int hash = key.hashCode();
int index =( hash & 0x7FFFFFFF) % table.length();
上一篇下一篇

猜你喜欢

热点阅读