手撕 简易HashMap

put()、get()、remove() 方法

计算存储数组位置和k-vNode节点

java 复制代码
    public int indexOf(K key){
        return key.hashCode() & (table.length - 1);
    }

    static class Node<K, V>{
        K key;
        V value;
        Node<K, V> next;
        public Node(K key, V value){
            this.key = key;
            this.value = value;
        }

    }
  • put(K key,V value)

向 HashMap 里存入数据的方法,逻辑是,先通过 hashCode() 方法获取 key 的 hash值,然后通过( n - 1) & hash 来得到该键值对存储在数据上的位置。

假如插入的位置没有数据,则直接插入,如果有数据,判断其key是否相同,如果相同就覆盖掉,如果不相同,就遍历这个"哈希桶"中的链表,将其 k-v 以链表的方式插入链表的尾部。

java 复制代码
public V put(K key, V value){
        int keyIndex = indexOf(key);
        Node<K, V> head = table[keyIndex];
        if(head == null){
            table[keyIndex] = new Node<>(key, value);
            size++;
            resizeIfNecessary();
            return null;
        }
        while(true){
            if(head.key.equals(key)){
                V oldValue = head.value;
                head.value = value;
                return oldValue;
            }
            if(head.next == null){
                head.next = new Node<>(key, value);
                size++;
                resizeIfNecessary();
                return null;
            }
            head = head.next;
        }
    }
  • get(K key)

获取 HashMap 里数据的方法,逻辑是,先通过 hashCode() 方法获取 key 的 hash值,然后通过( n - 1) & hash 来得到该键值对存储在数据上的位置。

假如该位置有数据并且与key相等,说明找到了直接返回,反之则遍历链表,没找到返回null。

java 复制代码
    public V get(K key){
        int keyIndex = indexOf(key);
        Node<K, V> head = table[keyIndex];
        while(head != null){
            if(head.key.equals(key)){
                return head.value;
            }
            head = head.next;
        }
        return null;
    }
  • remove(K key)

删除 HashMap 里数据的方法,逻辑是,先通过 hashCode() 方法获取 key 的 hash值,然后通过( n - 1) & hash 来得到该键值对存储在数据上的位置。

假如为null,说明没有返回null,如果在数组上则直接删除,并将下一个节点放在数组位置上,若数组没有则需遍历链表寻找。注意在删除后需 "接上链表" 。

java 复制代码
 public V remove(K key){
        int keyIndex = indexOf(key);
        Node<K, V> head = table[keyIndex];
        if(head == null){
            return null;
        }
        if(head.key.equals(key)){
            table[keyIndex] = head.next;
            size--;
            return head.value;
        }
        Node<K, V> pre = head;
        Node<K, V> current = head.next;
        while(current != null){
            if(current.key.equals(key)){
                pre.next = current.next;
                size--;
                return current.value;
            }
            pre = pre.next;
            current = current.next;
        }
        return null;
    }

扩容机制

负载因子为 0.75,也就是说当容量为 16 时,16 * 0.75 = 12 ,当存储第 13 个数据时,触发扩容机制。

扩容为原来数组的 2 倍。

遍历 HashMap 上的所有 k-v ,然后放在新的数组上。

java 复制代码
 private void resizeIfNecessary(){
        if(this.size < table.length * 0.75){
            return;
        }
        Node<K, V>[] newTable = new Node[table.length * 2];
        for(Node<K, V> head : this.table){
            if(head == null){
                continue;
            }
            Node<K, V> current = head;
            while(current != null){
                int newIndex = current.key.hashCode() & (newTable.length - 1);
                if(newTable[newIndex] == null){
                    newTable[newIndex] = current;
                    Node<K, V> next = current.next;
                    current.next = null;
                    current = next;
                } else {
                    Node<K, V> next = current.next;
                    current.next = newTable[newIndex];
                    newTable[newIndex] = current;
                    current = next;
                }
            }
        }
        this.table = newTable;
    }
相关推荐
庞轩px13 天前
第一篇:Redis数据结构底层——String、List、Hash、Set、ZSet各自用什么实现的?
数据结构·redis·list·set·hash·string·zset
七夜zippoe16 天前
DolphinDB分区策略:HASH分区与COMPO分区
算法·哈希算法·hash·dolphindb·compo
AI人工智能+电脑小能手21 天前
【大白话说Java面试题】【Java基础篇】第22题:HashMap 和 HashSet 有哪些区别
java·开发语言·哈希算法·散列表·hash
AI人工智能+电脑小能手21 天前
【大白话说Java面试题】【Java基础篇】第23题:ConcurrentHashMap的底层原理是什么
java·开发语言·算法·哈希算法·散列表·hash
AI人工智能+电脑小能手23 天前
【大白话说Java面试题】【Java基础篇】第19题:HashMap的key如何减少发生哈希冲突
java·开发语言·后端·面试·哈希算法·hash-index·hash
AI人工智能+电脑小能手23 天前
【大白话说Java面试题】【Java基础篇】第18题:HashMap底层是如何扩容的
java·开发语言·面试·散列表·hash-index·hash
深念Y24 天前
哈希与向量:计算机理解现实的两座桥梁
人工智能·数学·机器学习·向量·hash·哈希·空间
AI人工智能+电脑小能手1 个月前
【大白话说Java面试题】【Java基础篇】第7题:HashMap的get流程是什么
java·后端·面试·哈希算法·散列表·hash-index·hash
AI人工智能+电脑小能手1 个月前
【大白话说Java面试题】【Java基础篇】第5题:HashMap的底层原理是什么
java·开发语言·数据结构·后端·面试·hash-index·hash
Chen--Xing1 个月前
密码杂凑函数 -- 生日攻击
概率论·hash·生日攻击·crypto·杂凑函数