手写 HashMap

忙里偷闲,写了个 自己的HashMap,没有使用红黑树,仅是数组+单向链表的方式;
唯一的收货,大概就是理解了,为何阿里代码开发规范中,要求指定初始化的容量:因为每一次的resize都相当于,都是一个O(N)的操作;

/**
 * 基于数组+链表实现的hashMap
 *
 * @param <K>
 * @param <V>
 */
public class MyHashMap<K, V> {
    static class Entry<K, V> {
        K k;
        V v;
        Entry next;
        int hash;

        Entry(K k, V v, Entry next, int hash) {
            this.k = k;
            this.v = v;
            this.next = next;
            this.hash = hash;
        }
    }

    Entry[] table;
    int size;
    int capacity;
    static int default_capacity = 16;
    float threshold;
    static float default_threshold = 0.75f;

    public MyHashMap(int capacity, float threshold) {
        this.capacity = size < 2 << 4 ? default_capacity : capacity;
        this.threshold = threshold < 0 || Float.isNaN(threshold) ? default_threshold : threshold;
        table = new Entry[this.capacity];
    }

    public MyHashMap(int capacity) {
        this(capacity, default_threshold);
    }

    public MyHashMap() {
        this(default_capacity, default_threshold);
    }

    public V put(K k, V v) throws Exception {
        size++;
        resize(size);
        int index = hash(k);
        Entry<K, V> indexEntry = table[index];
        if (indexEntry == null) {
            indexEntry = new Entry<>(k, v, null, k == null ? 0 : k.hashCode());
            table[index] = indexEntry;
            return indexEntry.v;
        }
        while (indexEntry != null && indexEntry.next != null) {
            if (indexEntry.k.equals(k)) {
                V oldV = indexEntry.v;
                indexEntry.v = v;
                size--;
                return oldV;
            } else {
                indexEntry = indexEntry.next;
            }
        }
        if ((indexEntry.k == null && null == k) || (indexEntry.k != null && indexEntry.k.equals(k))) {
            V oldV = indexEntry.v;
            indexEntry.v = v;
            size--;
            return oldV;
        } else {
            indexEntry.next = new Entry(k, v, null, k.hashCode());
        }
        return v;
    }

    public V get(K k) throws Exception {
        int index = hash(k);
        Entry<K, V> indexEntry = table[index];
        while (indexEntry != null) {
            if ((indexEntry.k == null && null == k) || (indexEntry.k != null && indexEntry.k.equals(k))) {
                return indexEntry.v;
            } else {
                indexEntry = indexEntry.next;
            }
        }
        return null;
    }

    int hash(K k) {
        if (k == null) {
            return 0;
        }
        int index = k.hashCode() % capacity;
        return index;
    }

    void resize(int size) {
        if (size >= capacity * threshold) {
            capacity = capacity << 1;
            Entry[] oldTable = table;
            Entry[] newTable = new Entry[capacity];
            transfer(newTable);
            table = newTable;
        }
    }

    /**
     * 这就是构造器中指定capacity的原因,因为每一次扩容都是 O(N)
     *
     * @param newTable
     */
    void transfer(Entry[] newTable) {
        for (Entry<K, V> e : table) {
            while (null != e) {
                Entry next = e.next;
                int index = hash(e.k);
                Entry<K, V> entry = newTable[index];
                e.next = entry;
                newTable[index] = e;
                e = next;
            }
        }
    }

    public static void main(String[] args) throws Exception {
        MyHashMap<String, String> myHashMap = new MyHashMap<>();
        myHashMap.put(null, "null");
        System.out.println(myHashMap.get(null));
        myHashMap.put("1", "1");
        myHashMap.put("2", "2");
        myHashMap.put("3", "3");
        myHashMap.put("4", "4");
        myHashMap.put("5", "5");
        myHashMap.put("6", "6");
        myHashMap.put("7", "7");
        myHashMap.put("8", "8");
        myHashMap.put("9", "9");
        myHashMap.put("10", "10");
        myHashMap.put("11", "11");
        myHashMap.put("12", "12");
        myHashMap.put("13", "13");
        myHashMap.put("14", "14");
        myHashMap.put("15", "15");
        myHashMap.put("16", "16");
        myHashMap.put("17", "17");
        myHashMap.put("18", "18");
        myHashMap.put("19", "19");
        myHashMap.put("20", "20");


        System.out.println(myHashMap.get("1"));
        System.out.println(myHashMap.get("2"));
        System.out.println(myHashMap.get("3"));
        System.out.println(myHashMap.get("4"));
        System.out.println(myHashMap.get("5"));
        System.out.println(myHashMap.get("6"));
        System.out.println(myHashMap.get("7"));
        System.out.println(myHashMap.get("8"));
        System.out.println(myHashMap.get("9"));
        System.out.println(myHashMap.get("10"));
        System.out.println(myHashMap.get("11"));
        System.out.println(myHashMap.get("12"));
        System.out.println(myHashMap.get("13"));
        System.out.println(myHashMap.get("14"));
        System.out.println(myHashMap.get("15"));
        System.out.println(myHashMap.get("16"));
        System.out.println(myHashMap.get("17"));
        System.out.println(myHashMap.get("18"));
        System.out.println(myHashMap.get("19"));
        System.out.println(myHashMap.get("20"));
        System.out.println(myHashMap.size);
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值