hashmap和hashtable

要说说hashMap和hashTable的区别就要说说他们出现的时间顺序了:hashTable出现的比较早,hashMap出现的比较晚了;所以hashMap就对与hashTable进行了一些改进;
主要有一下方面:

  • hashMap是非线程安全的,所以效率比较高;
  • hashMap允许key和value为空;
    • 将key和value的null值改为0进行存储;如果不改的话存储null值时,用equals()方法时,会有空指针异常;
  • hashMap改原来的contains()方法为containsKey和containsValue();
  • hashTable()默认大小是11,扩容是2 * old + 1;而hashMap默认大小是16,且容量只能是2的幂;扩容2*old;
  • hashMap根据hashCode ^ hashcode >>> 16计算hash值,后取模数组的长度;而hashTable直接使用hashcode进行取模;
hashMap的数据结构

数组+链表+红黑树:

当冲突次数大于8时,首先考虑数组的扩容,当数组的长度大于64时,会将(冲突)链表改为红黑树;
当数组使用了75%的时候,进行数组扩容;

  • 为什么是8:
    • 泊松分布:定位到同一个位置的概率,在达到8此后,再次定位到此位置的概率为0;
  • 为什么是2的幂:
    • 扩容后重新定位方便
  • 0.75:是在0.5和1中取得中庸值;
几个关键阈值
  • 数组默认初始大小为16,初始化大小必须是2的幂次;
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
  • 最大容量,即数组的初始容量不能大于 2的30次方;
static final int MAXIMUM_CAPACITY = 1 << 30;
  • 负载因子,当数组使用了75%时,进行数组扩容;
static final float DEFAULT_LOAD_FACTOR = 0.75f;

*桶的树化阈值: 当链表长度大于8时,链表转红黑树;

static final int TREEIFY_THRESHOLD = 8;
  • 桶的链表还原阈值:当链表长度小于6时,红黑树转链表;
static final int UNTREEIFY_THRESHOLD = 6;
  • 最小树形化容量阈值:
static final int MIN_TREEIFY_CAPACITY = 64;
  • 扩容过程:当冲突次数大于8时,首先考虑数组的扩容,当数组的长度大于64时,会将(冲突)链表改为红黑树;当数组使用了75%的时候,进行数组扩容;
线程安全的 map

当我们需要HashMap是线程安全的时,怎么办呢?我们可以通过Collections.synchronizedMap(hashMap)来进行处理,亦或者我们使用线程安全的ConcurrentHashMap。ConcurrentHashMap虽然也是线程安全的,但是它的效率比Hashtable要高好多倍。因为ConcurrentHashMap使用了分段锁,并不对整个数据进行锁定。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值