实现简单版的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; } } }