实现自己的HashMap

通过实现自己的HashMap彻底了解HashMap的底层原理

  • JDK1.8 HashMap通过数组、链表、红黑树结构实现
  • 了解它的动态扩容、hash算法、存入元素、取出元素的过程

代码简单实现(省去树化,rehash):

public interface IMap<K,V> {

    void put(K k, V v);

    V get(Object k);

    void remove(Object k);

    int size();
}
public class MyHashMap<K ,V> implements IMap<K, V>{

    private final static int DEFAULT_CAPACITY = 1 << 3;
    private Node<K,V>[] table;
    private int size;


    static class Node<K,V> {
        final K k;
        V v;
        Node<K,V> next;

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

        @Override
        public String toString() {
            return "Node{" +
                    "k=" + k +
                    ", v=" + v +
                    ", next=" + next +
                    '}';
        }
    }


    @Override
    public void put(K k, V v) {
        Node<K,V>[] tab;
        Node<K,V> p;
        int i, n, h;
        //如果哈希表为null,在resize里面进行初始化
        if ((tab = table) == null || (n = table.length) == 0) {
            n = (tab = resize()).length;
        }
        //元素下标对应的位置中没有元素,直接入桶
        if ((p = tab[i = ((h = hash(k)) & (n-1))]) == null) {
            tab[i] = new Node<>(k,v,null);
        }else {
            //否则发生哈希碰撞,进行判断k是否相同
            Node<K,V> e;
            K k1;
            int hash = hash(k1 = p.k);
            //与哈希桶中k相同,e!=null
            if (hash == h && (Objects.equals(k, k1))) {
                //Objects.equals(k, k1) -->  return (a == b) || (a != null && a.equals(b));
                e = p;
            }else {
                //将新元素连到链表中
                while (true) {
                    //链表中k不重复,e == null
                    if ((e = p.next) == null) {
                        p.next = new Node<>(k,v,null);
                        break;
                    }
                    //与链表中k相同,e!=null
                    if (hash(e.k) == h && Objects.equals(e.k,k)) {
                        break;
                    }
                    p = e;
                }
            }
            //k值相同,进行value的替换
            if (e != null) {
                e.v =v;
                //重复的k,size不进行++操作,直接return
                return;
            }
        }
        if (++size > table.length) {
            resize();
        }

    }

    private int hash(Object k) {
        return k == null ? 0 : k.hashCode() ^ (k.hashCode()>>>16);
        //return 1;
    }

    private Node<K,V>[] resize() {
        Node<K,V>[] oldTable = table;
         int oldCap = (oldTable == null) ? 0 : oldTable.length;
         int newCap = 0;
         if (oldCap > 0) {
             newCap = oldCap << 1;
         }else {
             newCap = DEFAULT_CAPACITY;
         }
         @SuppressWarnings("unchecked")
         Node<K,V>[] newTable = (Node<K,V>[])new Node[newCap];
         table = newTable;
         if (oldTable != null) {
             //rehash
             //waiting...
         }
         return newTable;

    }

    @Override
    public V get(Object k) {
        Node<K,V> e;
        return (e = getNode(hash(k),k)) == null ? null : e.v;
    }

    private Node<K,V> getNode(int hash, Object k) {
        if (table == null || table.length == 0 || table[hash&(table.length - 1)] == null) {
            return null;
        }
        Node<K,V> first = table[hash&(table.length - 1)];

        if (hash(first.k) == hash && Objects.equals(first.k,k)) {
            return first;
        }
        Node<K,V> e;
        if ((e = first.next) != null) {
            do {
                if (hash(e.k) == hash && Objects.equals(e.k,k)) {
                    return e;
                }

            }while ((e = e.next) != null);
        }
        return null;
    }

    @Override
    public void remove(Object k) {
        //waiting...

    }

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

    @Override
    public String toString() {
        return "MyHashMap{" +
                "table=" + Arrays.toString(table) +
                '}';
    }
}
  • 测试结果:
public class Test {
    public static void main(String[] args) {
        MyHashMap<String,String> map = new MyHashMap<>();
        map.put("k1","v1");
        map.put("k2","v2");

        System.out.println(map.get("k1"));
        System.out.println(map.get("k2"));
        System.out.println(map.size());
        System.out.println(map);

        map.put("k2","vv");
        map.put("k3","v3");
        map.put("kk","vv");
        map.put("k1",null);
        System.out.println(map.get("k2"));
        System.out.println(map.get("k1"));
        System.out.println(map.size());
        System.out.println(map);
        map.put(null,null);
        System.out.println(map.size());
        System.out.println(map);

        /**
         * 结果:
         * v1
         * v2
         * 2
         * MyHashMap{table=[null, null, null, null, null, null, Node{k=k1, v=v1, next=null}, Node{k=k2, v=v2, next=null}]}
         * vv
         * null
         * 4
         * MyHashMap{table=[Node{k=k3, v=v3, next=Node{k=kk, v=vv, next=null}}, null, null, null, null, null, Node{k=k1, v=null, next=null}, Node{k=k2, v=vv, next=null}]}
         * 5
         * MyHashMap{table=[Node{k=k3, v=v3, next=Node{k=kk, v=vv, next=Node{k=null, v=null, next=null}}}, null, null, null, null, null, Node{k=k1, v=null, next=null}, Node{k=k2, v=vv, next=null}]}
         *
         *
         */

        /**
         * 测试哈希碰撞结果:(将hash()直接return 1;)
         * v1
         * v2
         * 2
         * MyHashMap{table=[null, Node{k=k1, v=v1, next=Node{k=k2, v=v2, next=null}}, null, null, null, null, null, null]}
         * vv
         * null
         * 4
         * MyHashMap{table=[null, Node{k=k1, v=null, next=Node{k=k2, v=vv, next=Node{k=k3, v=v3, next=Node{k=kk, v=vv, next=null}}}}, null, null, null, null, null, null]}
         * 5
         * MyHashMap{table=[null, Node{k=k1, v=null, next=Node{k=k2, v=vv, next=Node{k=k3, v=v3, next=Node{k=kk, v=vv, next=Node{k=null, v=null, next=null}}}}}, null, null, null, null, null, null]}
         *
         */

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值