hashMap的原理,手写hashMap

首先声明一下,这里我是根据源代码然后按照自己的思路总结出来的,可能有很多地方写的不够严谨或者原理说的不够准确,欢迎大家留言讨论和指正

1. hashMap的实现原理和不同点

  • JDK1.7中底层原理是数组链表的数据结构
  • JDK1.8中底层原理变成了 数组链表红黑树
  • JDK1.8中因为用了红黑树,所以Hash算法有所优化,写法也简化了一点
    (JDK1.7中是直接用key的hash值进行运算的。而1.8中对算法进行了优化,用key的hash值异或上key的hash值进行右移16位运算,让高低位参与运算,使元素分布更均匀)
  • JDK1.7的扩容机制是只要不小于阈值,就行扩容2倍
  • JDK1.8中优化成了
  1. 容量不超过64的话,扩容2倍
  2. 如果超过64,就查看桶中元素的个数,如果个数不小于7就将链表转换为红黑树,如果小于6就会还原为链表
  3. 红黑树中元素不小于32的时候才会再次扩容
  • JDK 1.7的插入方式的,将元素插到链表头部。而1.8则是插到链表尾部

2.手写HashMap

  • 声明必须的属性
public class MyHashMap<K, V> {

		/**
         * @Author: Pan
         * @Description: 链表是多个节点组成的,所以先创建一个节点对象(内部类),
         * @Date: 2020\4\12 0012 19:22
         */
    class Node<K, V> {
        /**
         * @Author: Pan
         * @Description: 键
         * @Date: 2020\4\12 0012 19:22
         */
        private K k;
        /**
         * @Author: Pan
         * @Description: 值
         * @Date: 2020\4\12 0012 19:23
         */
        private V v;
        /**
         * @Author: Pan
         * @Description: 节点指针
         * @Date: 2020\4\12 0012 19:23
         */
        private Node next;


        /**
         * @Author: Pan
         * @Description: 带参 构造
         * @Param: [k, v, next]
         * @Return:
         * @Date: 2020\4\12 0012 19:30
         */
        public Node(K k, V v, Node next) {
            this.k = k;
            this.v = v;
            this.next = next;
        }

        public K getK() {
            return k;
        }

        public void setK(K k) {
            this.k = k;
        }

        public V getV() {
            return v;
        }

        public void setV(V v) {
            this.v = v;
        }

        public Node getNext() {
            return next;
        }

        public void setNext(Node next) {
            this.next = next;
        }
    }
    }
  • 其他属性
/**
     * @Author: Pan
     * @Description: 容量大小
     * @Date: 2020\4\12 0012 19:11
     */
    private int size;

    /**
     * @Author: Pan
     * @Description: 最终用于存放元素的数组
     * @Date: 2020\4\12 0012 19:12
     */
    private Node[] data;

    /**
     * @Author: Pan
     * @Description: 默认容量
     * @Date: 2020\4\12 0012 19:12
     */
    private static final int DEFAULT_INITIAL_CAPACITY = 4;
  • 构造函数
/**
     * @Author: Pan
     * @Description: 空参构造 初始化数组大小
     * @Param: []
     * @Return:
     * @Date: 2020\4\12 0012 19:15
     */
    public MyHashMap() {
        this.data = new Node[DEFAULT_INITIAL_CAPACITY];
    }

    /**
     * @Author: Pan
     * @Description: 带参构造
     * @Param: [userCapacity]
     * @Return:
     * @Date: 2020\4\12 0012 19:16
     */
    public MyHashMap(int userCapacity) {
        if (userCapacity == 0) {
            throw new MyException(userCapacity + ",是不合法的容量值");
        } else {
            this.data = new Node[userCapacity];
        }
    }
  • put()set()size()toString()方法
 /**
     * @Author: Pan
     * @Description: put方法
     * @Param: [key, value]
     * @Return: void
     * @Date: 2020\4\12 0012 19:19
     */
    public void put(K key, V value) {
        //首先先根据 key 算出 hash 值,然后根据hash 值算出下标
        int keyHash = key.hashCode();
        int index = keyHash % data.length;
        //创建一个节点对象
        Node node = new Node(key, value, null);
        //如果hash冲突了 就把当前数组的下标放到节点的指针里
        if (data[index] != null) {
            node = new Node(key, value, data[index]);
        }
        data[index] = node;
        size++;
    }


    /**
     * @Author: Pan
     * @Description: map 的大小
     * @Param: []
     * @Return: int
     * @Date: 2020\4\12 0012 19:48
     */
    public int size() {
        return size;
    }

    /**
     * @Author: Pan
     * @Description: get 方法
     * @Date: 2020\4\12 0012 19:51
     */
    public Object get(K key) {
        //首先先根据 key 算出 hash 值,然后根据hash 值算出下标
        int keyHash = key.hashCode();
        int index = keyHash % data.length;
        //遍历数组找节点
        for (Node node = data[index]; node != null; node = node.next) {
            if(node.k.equals(key)){
                return node.v;
            }
        }
        return null;
    }

    @Override
    public String toString() {
        return "MyHashMap{" +
                "size=" + size +
                ", data=" + Arrays.toString(data) +
                '}';
    }

3. 测试
hashMap的原理,手写hashMap_第1张图片
hashMap的原理,手写hashMap_第2张图片

  • 最后总结一下,这是基于JDK1.7的源码写的(没有写扩容的部分),个人能力有限,看不懂1.8中的逻辑,哈哈哈哈 写不出来,希望大佬们多指点一下

你可能感兴趣的:(后端相关,java,hashmap)