HashMap底层原理(5)--- 使用LinkedList链表实现简易版HashMap

目录
-----第一章
----------为什么要深入学习HashMap?
----------HashMap与HashTable的区别是什么?
----------自定义HashMap中的Entry<K,V>类
----------使用ArrayList集合实现简易版HashMap
----------使用LinkedList链表实现简易版HashMap
----------HashCode和equals的区别
----------如何解决HashCode碰撞问题
----------纯手写HashMap中的put方法
----------纯手写HashMap中的get方法
-----第二章
----------HashSet基本API使用介绍
----------HashSet底层原理分析
----------HashMap底层基本实现原理分析
----------HashMap构造函数实现原理分析
----------HashMap第一次数组扩容原理
----------HashMapPut方法源码分析
-----第三章
----------HashMapJDK1.7面试题总结
----------HashMapJDK1.7扩容死循环原理分析
----------HashMapJDK1.8什么要使用红黑树
----------数据结构中时间复杂度对比
----------二叉搜索树基本实现原理与思想
----------手写二叉搜索树添加功能
----------手写二叉搜索树查询功能
----------总结二叉搜索查询存在哪些问题
-----第四章
----------二叉搜索树存在那些问题
----------红黑树的数据结构基本介绍
----------红黑树基本的特征介绍
----------红黑树变换颜色的规则要求
----------红黑树左右旋转基本的规则
----------手写红黑树环境代码实现
----------手写红黑树实现二叉树
----------红黑树规则破坏如何实现修复
-----第五章
----------手写红黑树左旋转代码演示
----------红黑树基本变色旋转规则回顾
----------纯手写一步一步写左旋转
----------红黑树基本左旋变颜色01
----------红黑树基本左旋变颜色02
----------红黑树基本左旋变颜色03
----------红黑树基本左旋变颜色04
----------红黑树查询左大值与最小值
-----第六章
----------HashMap8基本实现原理分析
----------HashMap8优化了7那些bug
----------HashMap8的Put方法实现原理01
----------HashMap8的Put方法实现原理02
----------HashMap8的Put方法扩容实现
----------HashMap8的Put方法源码分析总结

使用LinkedList链表实现HashMap

第一步:在HashMap中创建一个AaaryList集合来存放Entry<K,V>对象
 private LinkedList<Entry>[] list= new LinkedList[100];
第二步:使用简易的Hash算法,来提高查询效率
private int hash(K key) {
        int hashCode = key.hashCode();
        int hash = hashCode % list.length;
        return hash;
    }
第三步:重写put方法
    public V put(K key, V value) {
        // 1.计算到hash值
        int hash = hash(key);
		// 2.取出该位置的链表
        LinkedList<Entry> linkedList = list[hash];
        // 3.使用Key,Value创建Entry对象
        Entry entry = new Entry(key, value);
        //4.如果链表为null时
        if (linkedList == null) {
            // 5.创建链表
            linkedList = new LinkedList();
            // 6.把Entry对象添加到linkedList链表中
            linkedList.add(entry);
            // 7.数组指定位置存放链表
            list[hash] = linkedList;
            return value;
        }
        // 4.如果链表存在,遍历链表,判断Key是否存在
        for (Entry e : linkedList) {
            // 5.存在相同Key,覆盖旧值
            if (e.getKey().equals(key)) {
                e.setValue(value);
                return value;
            }
        }
        // 6.hashCode相同但是Key不同
        linkedList.add(entry);
        list[hash] = linkedList;
        return value;
    }
第四步:重写get方法
  public V get(K key) {
  		// 1.计算Hash值
        int hash = hash(key);
        // 2.获得指定下标的链表
        LinkedList<Entry> linkedList = list[hash];
        // 3.判断链表是否为null
         if (linkedList != null) {
         	  // 4. 遍历链表
        	  for (Entry e: linkedList) {
	            // 5.取出Key相同的value值
	            if (e.getKey().equals(key)) {
	                return (V) e.getValue();
	            }
       		 }
        }  
        return null;
    }
这时HashMap如下
public class MyHashMap<K, V> implements MyMap<K, V> {

  private LinkedList<Entry>[] list= new LinkedList[100];
  
  private int hash(K key) {
        int hashCode = key.hashCode();
        int hash = hashCode % list.length;
        return hash;
    }

  public V put(K key, V value) {
        // 1.计算到hash值
        int hash = hash(key);
		// 2.取出该位置的链表
        LinkedList<Entry> linkedList = list[hash];
        // 3.使用Key,Value创建Entry对象
        Entry entry = new Entry(key, value);
        //4.如果链表为null时
        if (linkedList == null) {
            // 5.创建链表
            linkedList = new LinkedList();
            // 6.把Entry对象添加到linkedList链表中
            linkedList.add(entry);
            // 7.数组指定位置存放链表
            list[hash] = linkedList;
            return value;
        }
        // 4.如果链表存在,遍历链表,判断Key是否存在
        for (Entry e : linkedList) {
            // 5.存在相同Key,覆盖旧值
            if (e.getKey().equals(key)) {
                e.setValue(value);
                return value;
            }
        }
        // 6.hashCode相同但是Key不同
        linkedList.add(entry);
        list[hash] = linkedList;
        return value;
    }

     public V get(K key) {
  		// 1.计算Hash值
        int hash = hash(key);
        // 2.获得指定下标的链表
        LinkedList<Entry> linkedList = list[hash];
        // 3.判断链表是否为null
         if (linkedList != null) {
         	  // 4. 遍历链表
        	  for (Entry e: linkedList) {
	            // 5.取出Key相同的value值
	            if (e.getKey().equals(key)) {
	                return (V) e.getValue();
	            }
       		 }
        }  
        return null;
    }

    static class Entry<K, V> implements MyMap.Entry<K, V> {
   
        private K k;

        private V v;
        
	    public Entry(K k, V v) {
            this.k = k;
            this.v = v;
        }
        public K getKey() {
            return this.k;
        }

        public V getValue() {
            return this.v;
        }
    }
}
这样用LinkedList链表就实现了一个简单的HashMap了,这样有什么缺点吗?

数组容量是固定的,当通过Hash方法计算出来的值相同的越来越多的时候,链表的长度就会越来越长,这时候get方法的时间复杂度就是O(n)了
这时候我们就应该去考虑扩容的问题了,什么时候该扩容?扩容多大?这个问题在JDK1.7的HashMap中有了解决方案

发布了12 篇原创文章 · 获赞 2 · 访问量 316

猜你喜欢

转载自blog.csdn.net/qq_42972645/article/details/104000656