HashMap原理和TreeMap原理

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的结果是完全相同的;当除数与被除数的符号不相同时,结果不同。
具体说,rem结果的符号与被除数相同;mod结果的符号与除数相同。
 
hashmap中添加元素:
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

 
  
 public V get(Object key) {
 
  
        if (key == null)
 
  
            return getForNullKey();
 
  
        int hash = hash(key.hashCode());
 
  
        //先定位到数组元素,再遍历该元素处的链表(hashcode无法直接定位到元素的地址)
 
  
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
 
  
             e != null;
 
  
             e = e.next) {
 
  
            Object k;
 
  
            if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
 
  
                return e.value;
 
  
        }
 
  
        return null;
 
  
}
 
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

转载于:https://www.cnblogs.com/jianmianruxin/p/7505694.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值