自己实现HashMap

实现简单版的HashMap

只是将map的添加,查询,扩容实现了

与JDK7源码中不同点,JDK中的hash函数是用到了很多的位运算,可以减少hash冲突,自己实现的HashMap只是简单利用了Object对象的hashCode函数

这里的扩容参考了JDK中的方法,涉及到引用传递,多看几遍就懂了

/**
 * 
 * table什么时候扩容的,threshold = capacity*loadfactor
 * 当size>threshold时,table扩容,数组长度增加为原长度的2倍,要重新计算hash值,重新把entry放入新的table中
 */
public class MyHashMap {

    private Entry[] table;
    private int capacity = 16;
    private float loadfactor = 0.75f;

    private int size;

    public MyHashMap() {
        table = new Entry[capacity];
    }

    public void put(Object key, Object value) {
        Entry toAdd = new Entry(key, value);
        int index = key.hashCode() % table.length;
        Entry entry = table[index];
        if (entry == null) { // index这一行还没有放入entry时
            table[index] = toAdd;
            size++;
        } else {
            for (Entry e = entry; e != null; e = e.next) {
                // 对于每一个Entry,先判断是不是要覆盖,也要判断是不是到了最后一个节点
                if ((e.key.hashCode() == key.hashCode()) && (e.key == key || e.key.equals(key))) {
                    e.value = value;
                    break;
                } else {
                    if (e.next == null) {
                        // 当前e是最后一个节点了 ,
                        // 将要添加的entry放在行首,他的next指向老的行首,
                        toAdd.next = table[index];
                        table[index] = toAdd;
                        size++;
                    }
                }
            }
        }
        if (size > capacity * loadfactor) {
            resize(capacity << 1); // 左移一位,相当与乘以2
        }
    }

    private void resize(int newCapacity) {
        System.out.println("扩容了............");
        Entry[] newTable = new Entry[newCapacity];
        Entry[] src = table;
        for (int i = 0; i < src.length; i++) {
            Entry entry = src[i];
            if (entry != null) {
                Entry e = entry;
                do {
                    Entry nextEntry = e.next; // 先保存当前节点的下一个,做为循环判断条件
                    int index = e.key.hashCode() % newCapacity;
                    e.next = newTable[index];
                    // 针对e.next = newTable[index]这里用到了引用赋值(值传递)
                    // 当为新数组的每一行第一次赋值时,当newTable[index]为null时,将当前entry的next是指向null
                    // 下一行执行newTable[index] = e;并不会更改e.next的值
                    // 当newTable[index]不为null时,当前entry的next指向的是数组index行行首.这样将entry连接起来了
                    newTable[index] = e; // 将当前entry放在数组的index行的行首
                    e = nextEntry;
                } while (e != null);
            }
        }
        table = newTable;
        capacity = newCapacity;

    }

    public Object get(Object key) {
        int index = key.hashCode() % table.length;
        Entry entry = table[index];
        for (Entry e = entry; e != null; e = e.next) {
            if (e.key.equals(key) || e.key == key) {
                return e.value;
            }
        }
        return null;
    }

    public static void main(String[] args) {
        MyHashMap extHashMap = new MyHashMap();
        extHashMap.put("1号", "00");// 0
        extHashMap.put("2号", "00");// 1
        extHashMap.put("3号", "00");// 2
        extHashMap.put("4号", "00");// 3
        extHashMap.put("6号", "6号");// 4
        extHashMap.put("7号", "00");
        extHashMap.put("14号", "00");
        extHashMap.put("22号", "00");
        extHashMap.put("26号", "26号");
        extHashMap.put("27号", "00");
        extHashMap.put("28号", "00");
        extHashMap.put("66号", "00");
        extHashMap.put("26号", "^^^^^");
        extHashMap.print();
        System.out.println("============================");
        extHashMap.put("30号", "00");
        extHashMap.print();
        System.out.println(extHashMap.get("26号"));

    }

    public void print() {
        for (int i = 0; i < table.length; i++) {
            System.out.print("下标[" + i + "] ");
            for (Entry e = table[i]; e != null; e = e.next) {
                System.out.print("【key = " + e.key + ",value = " + e.value + "");
            }
            System.out.println();
        }

    }

    class Entry {
        Object key;
        Object value;
        Entry next;

        public Entry(Object key, Object value) {
            this.key = key;
            this.value = value;
        }

    }
}

 

引用传递的例子

    @SuppressWarnings("unused")
    public static void main(String[] args) {
         User [] arr = new User[10];
         User u1  =  arr[0]; //引用传递也是值传递,u1指向了null对象
         arr[0]  =  new User("李四"); //给arr[0]赋值,即arr[0]指向了一个新的地址,这时u1还是null
         System.out.println();
    }

    static class User{
        String name;
        public User(String name) {
            super();
            this.name = name;
        }
    }
}
posted @ 2019-06-28 14:03  踏月而来  阅读(648)  评论(0编辑  收藏  举报