简单实现HashMap

本文介绍了HashMap在不同版本(1.6, 1.7, 1.8)中的变化,包括哈希冲突解决策略和数据结构升级。重点讲解了散列核心、哈希函数以及扩容和冲突处理方法。通过实例代码演示了如何操作和解决哈希冲突。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简单实现HashMap

理论

  • JDK 1.6, JDK 1.7 HashMap 采用位桶(数组) + 链表实现。
  • JDK 1.8 HashMap 采用位桶(数组) + 链表 + 红黑树实现。(当链表长度超过阈值 “8” 时,将链表转换为红黑树)

哈希冲突

  • 利用哈希冲突特性 存取数据
  • 定义一个链表数组 Node[] data = new Node[16];
  • put 的时候,通过hashCode算出在data数组中索引,2种情况
    1. hash值算出的索引一样,key不一样,存入链表 (hash冲突)
    2. hash值算出的索引一样,key一样 ,放弃存入
  • get 的时候,通过hashCode算出在data数组中索引,2种情况
    1. hash值算出的索引一样,key不一样 ,遍历链表,比对key
    2. hash值算出的索引一样,key一样 ,直接返回

实践代码(简单实现)

public class HashNode {

    Node[] data = new Node[16];
    int max_count = 16;
    int count = 0;

    //HashMap的容量
    int indexFor(int h, int length) {  //散列核心
        return h & (length - 1);
    }

    final int hash(Object k) {
        int h = 0;
        //得到k的hashcode值
        h ^= k.hashCode();
        //进行计算
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }

    public Object get(Object key) {
        if (key == null)
            return null;
        Node entry = getEntry(key);

        return null == entry ? null : entry.value;
    }

    //数据获取
    final Node getEntry(Object key) {
        int hash = (key == null) ? 0 : hash(key);
        for (Node e = data[indexFor(hash, data.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                return e;
        }
        return null;
    }


    //数据存入
    private void addEntry(int hash, Object key, Object value, int i) {

        if (count > max_count * 0.75) {//12
            //扩容
        }
        //存入
        Node node = new Node();
        node.hash = hash;
        node.key = key;
        node.value = value;
        System.out.println("index i = " + i + " key = " + key);
        if (data[i] == null) {
            data[i] = node;
        } else {
            System.out.println("hash冲突");
            Node end_node = reverseList(data[i]);
            end_node.next = node;
        }
    }

    public static Node reverseList(Node head) {

        Node tempNode;
        Node curNode = head;
        while (curNode.next != null) {
            tempNode = curNode.next;
            curNode = tempNode;
        }

        return curNode;
    }

    public Object put(Object key, Object value) {

        //通过调用hash方法对key进行哈希,得到哈希之后的数值。
        // 该方法实现可以通过看源码,其目的是为了尽可能的让键值对可以分不到不同的桶中
        int hash = hash(key);

        int i = indexFor(hash, data.length);

        //已经存在数据
        for (Node e = data[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                Object oldValue = e.value;
                e.value = value;
                return oldValue;
            }
        }

        count++;
        addEntry(hash, key, value, i);
        return null;
    }

}

使用


 //自定义hashMap  未加入扩容机制
        HashNode hashNode = new HashNode();
        hashNode.put(1, "A");
        hashNode.put(2, "B");
        hashNode.put(12, "C");
        hashNode.put(13, "D");
        hashNode.put(14, "E");
        hashNode.put(20, "F");
        hashNode.put(15, "G");
        hashNode.put(18, "H");
        hashNode.put(19, "Z");
        hashNode.put(10, "Y");
        System.out.print("" + hashNode.get(1));
        System.out.print("" + hashNode.get(2));
        System.out.print("" + hashNode.get(12));
        System.out.print("" + hashNode.get(13));
        System.out.print("" + hashNode.get(14));
        System.out.print("" + hashNode.get(20));
        System.out.print("" + hashNode.get(15));
        System.out.print("" + hashNode.get(18));
        System.out.print("" + hashNode.get(19));
        System.out.println("");
        //其中 2 和19 hash冲突
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值