hashmap的底层以及实现

Map用作什么场景,hashMap和hashTable有什么区别


详细请参考文章来源:http://blog.csdn.net/justloveyou_/article/details/62893086?locationNum=2&fps=1

1.map是key-value对映射的接口,通过hash算法来实现key-value的位置存储,从而快速高效的存取

2.hash算法:hash算法是一个集合到另一个集合的映射,key键的集合到value值集合的映射,这个映射要求考虑时间复杂度和空间复杂度,同时还有冲突碰撞

3 hash构造函数的方法有多种,如直接订址,数字分析,折叠,平方取中等等方法

4 HashMap的构造方法,hashMap的构造方法一般会默认有个容量为16,还有一个负载因子参数0.75;

对于hashMap我们应该知道哪些


看下面的5点之前我们先说说hashmap的数据结构

key-value键值对:key和value是如果存储的?hashMap的对象是Entry<k,V>

key通过hash算法(也就是hashcode)会得到一个int类型的值,一个int类型的值会对应数组的一个下标,

即找到这个桶,然后遍历这个桶(链表),找到value的值

1,hashMap效率高,线程不安全,hashTable实现了同步锁,线程安全,效率低,目前线程安全的一般用concurrenthashMap

2、如果两个对象equals,Java运行时环境会认为他们的hashcode一定相等。

3、如果两个对象不equals,他们的hashcode有可能相等。
4、如果两个对象hashcode相等,他们不一定equals(我理解是由于hash冲突造成的)。
5、如果两个对象hashcode不相等,他们一定不equals。

一 hashmap的构造函数

public HashMap(){
    //负载因子,说明hashMap的空间使用情况,默认是0.75
     this.loadFactor = DEFAULT_LOAD_FACTOR; 
     //进行扩容的阈值,默认负载因子*默认容量值,默认容量值为16
     threshold=(int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
     //hashMap的底层仍然是数组,数组里存放的链表形式的数据
      table = new Entry[DEFAULT_INITIAL_CAPACITY];
      init();
}
初始容量 负载因子,这两个参数是影响HashMap性能的重要参数。其中, 容量表示哈希表中 桶的数量 (table 数组的大小),初始容量是创建哈希表时桶的数量;负载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度,它衡量的是一个散列表的空间的使用程度,负载因子越大表示散列表的装填程度越高,反之愈小。  对于使用 拉链法(下文会提到)的哈希表来说,查找一个元素的平均时间是 O(1+a),a 指的是链的长度,是一个常数。特别地,若负载因子越大,那么对空间的利用更充分,但查找效率的也就越低;若负载因子越小,那么哈希表的数据将越稀疏,对空间造成的浪费也就越严重。 系统默认负载因子为 0.75,这是时间和空间成本上一种折衷,一般情况下我们是无需修改的

hash的数据结构

1,hash()算法:hash就是把一个key值通过hash算法转换为一个int型整数,他是一种压缩映射,压缩后的hash值不一定和原来的key数量相等

2,hashmap是数组数据结构和链表数据结构的结合;hashMap的内部对象是一个Entry<K,V数组>;Entry数组的结构如下:

public static class Entry
   
   
    
     implements Map.Entry
    
    
     
     {
    final K key;//key
    V value;//value
    Entry
     
     
      
       next;//指向下一个节点
    final int hash;//hash(Key.hashCode())返回值
    
    public Entry(int h, K k, V v, Entry
      
      
       
        n){
        value = v;
        next = n;
        key = k;
        hash = h;
    }
}
      
      
     
     
    
    
   
   
3,HashMap 中,键值对的存储是通过 put(key,vlaue) 方法来实现的

首先,判断key是否为null,若为null,则直接调用putForNullKey方法;若不为空,则先计算key的hash值,然后根据hash值搜索在table数组中的索引位置,如果table数组在该位置处有元素,则查找是否存在相同的key,若存在则覆盖原来key的value,否则将该元素保存在链头(最先保存的元素放在链尾)。此外,若table在该处没有元素,则直接保存

public V put(K key, V value) {

        //当key为null时,调用putForNullKey方法,并将该键值对保存到table的第一个位置 
        if (key == null)
            return putForNullKey(value); 

        //根据key的hashCode计算hash值
        int hash = hash(key.hashCode());             //  ------- (1)

        //计算该键值对在数组中的存储位置(哪个桶)
        int i = indexFor(hash, table.length);              // ------- (2)

        //在table的第i个桶上进行迭代,寻找 key 保存的位置
        for (Entry
   
   
    
     e = table[i]; e != null; e = e.next) {      // ------- (3)
            Object k;
            //判断该条链上是否存在hash值相同且key值相等的映射,若存在,则直接覆盖 value,并返回旧value
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;    // 返回旧值
            }
        }

        modCount++; //修改次数增加1,快速失败机制

        //原HashMap中无该映射,将该添加至该链的链头
        addEntry(hash, key, value, i);            
        return null;
    }
   
   

上述的hash()方法和indexFor()方法的作用只有一个:保证元素均匀分布到table的每个桶中以便充分利用空间


更多了解参考http://blog.csdn.net/justloveyou_/article/details/62893086?locationNum=2&fps=1

这里的解释更详细也更深入,我这里只是自己学习了解





   



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值