HashMap底层实现和原理分析(资料源自于源码学院)

 

 

一、Map的快速开始

Map map=new HashMap();

//map的添加数据

map.put("name","小明")

map.put("age","28")

//从map中获取数据

map.get("name")

二、Map的技术实现

HashMap的底层实现是:数组+链表+红黑树(jdk8以后加入红黑树)

数组的概念:采用一段连续的存储单元来存储数据

数组的特点是:查询快,插入慢

链表的概念:链表是一种物理存储单元上非连续、非顺序的数据结构

链表的特点:插入快,查询慢

手动实现简易版0HashMap

map接口

package cn.shiyujun.hashMap;

public interface Map<K,V> {

    V put(K k,V v);

    V get(K k);

    int size();

    interface  Entry<K,V>{
         K  getKey();
         V  getValues();
    }

}

HashMap的实现 

package cn.*.hashMap;

public class HashMap<K,V> implements Map<K,V> {
    private  Entry<K,V>[] table=null;
    int size=0;

    public HashMap() {
        //定义数组长度为16
      table=new Entry[16];
    }
    @Override
    public V put(K k, V v) {
        //获取k的hash值
        int index=hash(k);
        //获取该索引下的值判断是否存在
        Entry<K, V> entry = table[index];
        if(null==entry){
            //entry为null说明该索引没有对应的值是第一次添加值所以next为null
            table[index]=new  Entry<K,V>(k,v,index,null);
            size++;
        }else{
            //entry不为null说明该索引已经存在值根据链表的规则原值移一位,next赋值为当前值
            table[index]=new Entry<K,V>(k,v,index,entry);
        }

        return table[index].getValues();
    }

    private int hash(K k) {
        int index = k.hashCode() % 15;
        //可能存在负数需要转称正
        return Math.abs(index);

    }

    @Override
    public V get(K k) {
        if(size==0){
            return null;
        }
        //计算hash值
        int index = hash(k);
        Entry<K, V> entry = getEntry(k, index);
        return entry==null?null:entry.getValues();
    }

    private Entry<K, V> getEntry(K k, int index) {
       for (Entry<K, V> e = table[index]; e!=null; e=e.next){
            if(null!=e&&e.hash==index&&(k==e.getKey()||e.getKey().equals(k))){
                  return e;
            }
        }

        return null;
    }

    @Override
    public int size() {
        return size;
    }

    class Entry<K,V>  implements   Map.Entry<K,V>{
         K k;
         V v;
         int hash;
         Entry<K,V> next;

        public Entry(K k, V v, int hash, Entry<K, V> next) {
            this.k = k;
            this.v = v;
            this.hash = hash;
            this.next = next;
        }

        @Override
        public K getKey() {
            return k;
        }

        @Override
        public V getValues() {
            return v;
        }
    }

}

引入红黑树

链表的特点是:查询速度慢

红黑树特点:查询快,插入慢

阈值为:7

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
哈希表(Hashmap)是一种常见的数据结构,它的底层实现原理主要基于哈希函数和数组。当插入、查找或删除元素时,首先通过哈希函数将键(key)转换为一个索引值,然后在对应的数组位置存储或访问值。这种操作通常具有常数时间复杂度O(1),但在哈希冲突较多时效率会下降。 哈希冲突是指不同的键可能计算出相同的索引。处理哈希冲突的方法有很多种,最常见的有两种: 1. **开放寻址法**(Open Addressing):遇到冲突时,寻找下一个空闲的位置存放元素,直到找到合适的为止。比如线性探测(Linear Probing)、二次探测(Quadratic Probing)或双散列(Double Hashing)。 2. **链地址法**(Separate Chaining):每个数组元素不再直接存储值,而是指向一个链表,将所有冲突的元素放在相应的链表中。当我们按索引查找时,如果该位置不是我们想要的值,就沿着链接链表继续查找。 扩容机制是为了应对数据增加导致的哈希冲突增多。当哈希表的装载因子(已存储元素数量/总容量)超过预设阈值,通常为0.75或0.8,系统会选择扩大哈希表的大小,新表通常是原表的两倍。扩容的具体步骤包括: - 创建一个新的更大的哈希表。 - 遍历旧表中的每一个元素,重新计算新的键对应的索引,并把元素插入到新表的相应位置。 - 将旧表的数据迁移至新表。 - 更新旧表为只读状态,或者销毁旧表以释放内存。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值