package example.java; /** * @author 杜科 * @description 定製化的HashMap * 當量級爲百萬級時,比起HashMap<Integer,V> put提高超8倍,get提高超10倍。彷佛此時最佳 * 當量級增大到千萬級時,put的性能比HashMap持平,甚至稍弱,get的性能爲HashMap 4倍 * @contact AllenDuke@163.com * @date 2020/7/16 */ public class IntHashMap<V> { private class IntEntry<V> { int key; V value; IntEntry next; } private IntEntry[] table; private int capacity;//2的n次方 public IntHashMap(int capacity) { if(!checkCapacity(capacity)) throw new RuntimeException("capacity:"+capacity+",不是2的n次方"); this.capacity = capacity; table = new IntEntry[capacity]; } //檢查容量是否爲2的n次方 按位檢查1的個數 public static boolean checkCapacity(int capacity) { int oneCount = 0; for (int i = 0; i < 32; i++) { if ((capacity & 1) == 1) oneCount++; capacity >>>= 1; } if (oneCount == 1) return true; else return false; } //性能比checkCapacity稍好 public static int bitCount(int i) { // HD, Figure 5-2 i = i - ((i >>> 1) & 0x55555555); i = (i & 0x33333333) + ((i >>> 2) & 0x33333333); i = (i + (i >>> 4)) & 0x0f0f0f0f; i = i + (i >>> 8); i = i + (i >>> 16); return i & 0x3f; } //todo 更爲更優秀的hash函數 private static int indexFor(int key, int length) { return key & (length - 1); } public void put(int key, V value) { IntEntry<V> entry = new IntEntry<>(); entry.key = key; entry.value = value; int i = indexFor(key, table.length); IntEntry head = table[i]; if (head == null) { table[i] = entry; return; } while (head.next != null) head = head.next; head.next = entry; } public V get(int key) { int i = indexFor(key, table.length); IntEntry<V> head = table[i]; while (true) { if (head == null) return null;//不作檢查使用者保證,減小運算 if (head.key == key) return head.value; head = head.next; } } }
減小Integer的生成java
簡單測試函數
package example.java; import java.util.HashMap; /** * @author 杜科 * @description * @contact AllenDuke@163.com * @date 2020/7/16 */ public class IntHashMapTest { public static void main(String[] args) { int count=1024*1024; System.out.println("current count:" + count); HashMap<Integer, Integer> hashMap = new HashMap<>(count); IntHashMap<Integer> intHashMap = new IntHashMap<Integer>(count); long start1=System.currentTimeMillis(); for(int i=0;i<count;i++){ hashMap.put(i*31,i); } long finish1=System.currentTimeMillis(); System.out.println("HashMap put cost:"+(finish1 - start1) + "ms"); start1=System.currentTimeMillis(); for(int i=0;i<count;i++){ hashMap.get(i*31); } finish1=System.currentTimeMillis(); System.out.println("HashMap get cost:"+(finish1 - start1) + "ms"); long start2=System.currentTimeMillis(); for(int i=0;i<count;i++){ intHashMap.put(i*31,i); } long finish2=System.currentTimeMillis(); System.out.println("IntHashMap put cost:"+(finish2 - start2) + "ms"); start2=System.currentTimeMillis(); for(int i=0;i<count;i++){ intHashMap.get(i*31); } finish2=System.currentTimeMillis(); System.out.println("IntHashMap get cost:"+(finish2 - start2) + "ms"); for(int i=0;i<count;i++){ if(!hashMap.get(i*31).equals(intHashMap.get(i*31))) throw new RuntimeException("IntMap error key:"+i*31+" hashMap:"+hashMap.get(i*31)+" intHashMap:"+intHashMap.get(i*31)); } start1=System.currentTimeMillis(); for(int i=0;i<count;i++){ IntHashMap.checkCapacity(i); } finish1=System.currentTimeMillis(); System.out.println("IntHashMap checkCapacity cost:"+(finish1 - start1) + "ms"); start2=System.currentTimeMillis(); for(int i=0;i<count;i++){ IntHashMap.bitCount(i); } finish2=System.currentTimeMillis(); System.out.println("IntHashMap bitCount cost:"+(finish2 - start2) + "ms"); } }