hashmap,hashset,hashtable区别

作为一个比较经典的面试题。从伯乐在线看到了几个比较经典的文章

引用链接:

http://www.importnew.com/7099.html

这篇文章讲的是hashmap面试用的一些问题。

引申到java最底层的equals 和 hashcode()方法。

hashcode一样,equals不一定一样,但equals一样,hashcode一定一样!

默认情况下。equals为直接 this == obj 进行对比,而hashcode()为底层调用其他方法进行实现。


那么 hashmap基于hashing原理,键值对存储模式,为集合类的一个具体实现类。

当hashmap 存键值对时,这里为map.entry.也就是put(k,v)时,从源码来看,但调用put方法时,

首先判断key是否为空,hashmap允许为null,return putfornullKey(v);

public V put(K key, V value) {
	// 处理key为null,HashMap允许key和value为null
	if (key == null)
		return putForNullKey(value);
	// 计算key值的hash 
	int hash = hash(key);
	// 通过哈希码计算出bucketIndex
	int i = indexFor(hash, table.length);
	// 取出bucketIndex位置上的元素,并循环单链表,判断key是否已存在
	for (Entry<K,V> e = table[i]; e != null; e = e.next) {
		Object k;
		// 哈希码相同并且对象相同时
		if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
			// 新值替换旧值,并返回旧值
			V oldValue = e.value;
			e.value = value;
			e.recordAccess(this);
			return oldValue;
		}
	}

	// key不存在时,加入新元素
	modCount++;
	addEntry(hash, key, value, i);
	return null;
}
计算出key的hash,通过hash计算出bucketIndex这个位置,,因为k.v键值对都存放在hashmap里一个叫做bucket的地方,一个bucket作为一个map.entry来取对象,这是取对象迭代器的逻辑。

判断,这个位置如果没元素,直接添加,如果有元素 循环这个位置的元素的key,如果 hash相同 并且equals相同时,新V替换旧V,如果hash相同,但是equals不相同时,这就是碰撞现象,因为hashmap是通过链表来维护键值对的,所以在这个bucket里面有有一个单链表去维护这些键值对。将新元素(新的map.entry)加入到表头。

那么出现碰撞的话,取得时候怎么办呢。取用的是 get方法 通过key的hash获取到bucket然后遍历所有元素,通过equals方法来判断自己真正想要的值。

为了尽量避免发生碰撞现象,尽量使用string,integer这种不可变的final类型的作为Key,也可以使用自定义的对象,只要能保证对象不可变就是了。

当hashmap的负载因子达到总体容量的75%时,会默认扩充到本身的两倍。因为hashmap本身为非同步的,线程不安全类型,在保证了速度的同时,牺牲了安全性,导致容易在多线程的情况下,多个线程同时进行对一个hashmap进行扩容的情况,这种现象叫做条件竞争,因为在扩容的同时,里面存在的元素会放到整个map的头部,这是为了避免尾部遍历,所以容易导致死循环。那么这种多线程的情况下。为什么要用 非线程安全的hashmao????

hashmap hashtable的区别

都继承了map,更多的区别表现在,线程安全性,速度 和 同步上

在存储上,两者基本相同,hashmap只是多了允许存放null的键值对上。同时,他的元素存放顺序是不一定的!

在线程安全性上,hashmap为非安全,table反之,多个线程是允许共享一个table的,但如果没有安全的同步情况下,hashmap是不安全的,同时在jdk1.5之后出现了一个concrrenthashmap,他是table的代替品,有更好的扩展性!

在速度上,因为hashmap的非安全性,导致了在单线程下他的速度比table要快。


hashmap hashset的区别

                        hashmap,          hashset

接口                  map                                     set

                    键值对存储                           对象存储

            存储时以key来hashcode       存储时以对象来hashcode

                    速度稍比hashset快



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值