http://www.importnew.com/7099.html及文章下方评论
http://blog.csdn.net/vking_wang/article/details/14166593超赞
http://blog.csdn.net/ghsau/article/details/16890151容量加载因子
HashMap数据结构用数组和链表形式实现:
每个数组中存储的是链表的头元素。每个元素是个entry,包含键和值。
hashmap的get(key)方法得到的是key对应的value,并不是key-value键值对。
用了hashing(哈希算法)来查找???(目前来看查找没有完全用哈希算法)
调用put方法存储元素时,会先调用hashcode()方法返回键的hashcode,键的hashcode对数组的长度进行取余运算,得到的值便是桶的位置,比如两个元素的key的hashcode为12和28,数组长度为16,取余的结果都是12,将一起存储在数组下标为12的位置,存储entry实体(不是只存储值哦)。之后调用Map.entry可以获取。
上面hashcode为12和28的key,其对应实体往下标相同的数组中put时怎么put?任何一个元素进来存在数组(数组中存的是最后一个插入的元素),并且该数组的元素有entry属性,其中的next会指向前一个存在数组中的元素。
HashMap有两个参数影响其性能:初始容量和加载因子。默认初始容量是16还是2的冪次????,加载因子是0.75。容量是哈希表中桶(Entry数组)的数量。初始容量是哈希表创建时的容量,加载因子是哈希表在其容量自动增加前可以达到多满的一种尺度。当哈希表中条目数????超出了加载因子与当前容量的乘机,通过调用rehash方法将容量翻倍。
void addEntry(int paramInt1, K paramK, V paramV, int paramInt2)
{
Entry localEntry = this.table[paramInt2];
this.table[paramInt2] = new Entry(paramInt1, paramK, paramV, localEntry);
if (this.size++ >= this.threshold)
resize(2 * this.table.length);
}
覆盖和哈斯算法,16还是2的冪次???????concurrentHashMap和hashtable的区别,set存相同的情况,覆盖equals()需要覆盖hashCode()?
对hashcode()方法进行再哈希的原因:
本身hashcode是一个int型的值,取值范围有40多亿空间。只要哈希函数映射比较均匀松散,一般不会出现哈希碰撞。但是!由于想把各个对象均匀的分不到hashmap的桶中,因此需要对hashcode做取模运算,取模运算保留的是低位区的数字,比如hashmap桶的数量为16时,对hashcode取模保留的是低四位的数字。对于两个对象的hashcode,32位的hashcode一样的情况少,但它们的低四位一样的情况概率挺大的,因此必须对hashcode的低位增加随机性。可以直接对低位使用随机函数,因此采用高低位进行异或运算来增加低位的随机性,以便对象可以在不同的桶中随机分布。
java中%表示取余
取余和取模的区别是:在计算商时,取余向正方向舍入得到商,取模则是向负方向舍入得到商。(取模运算必须至少用一个double型做除法,两个int型的数除法只是取整,整数取模的结果有问题)
具体说,rem结果的符号与被除数相同;mod结果的符号与除数相同。
public V put(K key, V value) { // 若“key为null”,则将该键值对添加到table[0]中。 if (key == null) return putForNullKey(value); // 若“key不为null”,则计算该key的哈希值,然后将其添加到该哈希值对应的链表中。 int hash = hash(key.hashCode()); //搜索指定hash值在对应table中的索引 int i = indexFor(hash, table.length); // 循环遍历Entry数组,若“该key”对应的键值对已经存在,则用新的value取代旧的value。然后退出! 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))) { //如果key相同则覆盖并返回旧值 V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } //修改次数+1 modCount++; //将key-value添加到table[i]处 addEntry(hash, key, value, i); return null;}
hashset添加元素
public boolean add(E paramE)
{
return this.map.put(paramE, PRESENT) == null;
}
由此知当hashset添加重复元素会返回null(因为hashmap添加key相同的元素时更新value后返回原始value而不是null)
hashmap根据key获取元素:
2)get
hash():
static
final
int
hash(Object key) {
int
h;
return
(key ==
null
) ?
0
: (h = key.hashCode()) ^ (h >>>
16
);
}
hashcode右移16位左边补0后与原hashcode异或运算增加低位随机性。
TreeMap
TreeMap基于红黑树实现
主要用于存入元素的时候对元素进行自动排序,迭代输出的时候就按排序顺序输出。
TreeMap中key不能为null
http://www.cnblogs.com/wzyxidian/p/5204879.html