HashMap 实现总结

  1. Entry类中需包含键值的hash值,防止resize时的重复计算;
  2. Map容量为2的整幂,可使用位操作取代取余操作提高效率;
  3. resize时需要将原table的桶内数据置null,利于垃圾回收;
  4. hash函数考虑数据高位的影响,可减少冲突。
  1 public class MyHashMap<K, V> implements IMap<K, V> {
  2     static final float DEFAULT_LOAD_FACTOR = 0.75f;
  3     static final int DEFAULT_CAPACITY = 16;
  4 
  5     Entry<K, V>[] table;
  6     int size;
  7     /**
  8      * 装载因子
  9      */
 10     float loadFactor;
 11     /**
 12      * 实际的容量
 13      */
 14     int threshold;
 15 
 16     public MyHashMap() {
 17         this.loadFactor = DEFAULT_LOAD_FACTOR;
 18         this.threshold = (int) (DEFAULT_CAPACITY * loadFactor);
 19         table = new Entry[DEFAULT_CAPACITY];
 20     }
 21 
 22     public MyHashMap(int initialCapacity, float loadFactor) {
 23         /**
 24          * 缺少参数检查
 25          */
 26         int capacity = 1;
 27         while (capacity < initialCapacity) {
 28             capacity <<= 1;
 29         }
 30         this.loadFactor = loadFactor;
 31         this.threshold = (int) (capacity * loadFactor);
 32         table = new Entry[capacity];
 33     }
 34 
 35     public MyHashMap(int initialCapacity) {
 36         this(initialCapacity, DEFAULT_LOAD_FACTOR);
 37     }
 38 
 39     /**
 40      * 算术右移,计入高位影响
 41      */
 42     static int hash(int h) {
 43         return h ^ (h >>> 20) ^ (h >>> 12) ^ (h >>> 7) ^ (h >>> 4);
 44     }
 45 
 46     @Override
 47     public V put(K k, V v) {
 48         if (k == null) {
 49             putForNull(v);
 50         }
 51         int hash = hash(k.hashCode());
 52         int i = indexFor(hash, table.length);
 53         for (Entry<K, V> e = table[i]; e != null; e = e.next) {
 54             if (e.key.hashCode() == k.hashCode()
 55                     && (e.key == k || (k != null && k.equals(e.key)))) {
 56                 V oldValue = e.value;
 57                 e.value = v;
 58                 return oldValue;
 59             }
 60         }
 61         addEntry(k, v, i);
 62         return null;
 63     }
 64 
 65     private void addEntry(K k, V v, int index) {
 66         Entry<K, V> e = new Entry<K, V>(k, v, table[index]);
 67         table[index] = e;
 68         if (size++ > threshold) {
 69             resize(table.length * 2);
 70         }
 71     }
 72 
 73     void resize(int newCapacity) {
 74         Entry[] newTable = new Entry[newCapacity];
 75         transfer(newTable);
 76         table = newTable;
 77         threshold = (int) (newCapacity * loadFactor);
 78         System.out.println("resize()" + " current capacity: " + table.length);
 79     }
 80 
 81     void transfer(Entry[] newTable) {
 82         for (int i = 0; i < table.length; i++) {
 83             Entry<K, V> e = table[i];
 84             if (e != null) {
 85                 /**
 86                  * 需要將原table置为空,方可释放内存
 87                  */
 88                 table[i] = null;
 89                 do {
 90                     Entry<K, V> next = e.next;
 91                     /**
 92                      * 重复计算hash值,效率不高
 93                      */
 94                     int index = indexFor(hash(e.key.hashCode()),
 95                             newTable.length);
 96                     e.next = newTable[index];
 97                     newTable[index] = e;
 98                     e = next;
 99                 } while (e != null);
100             }
101         }
102     }
103 
104     private V putForNull(V value) {
105         // 未实现
106         return value;
107     }
108 
109     /**
110      * 用位操作取代取余操作,前提是数组长度为2的幂次
111      */
112     private int indexFor(int hash, int length) {
113         return hash & (length - 1);
114     }
115 
116     @Override
117     public V get(K k) {
118         int hash = hash(k.hashCode());
119         int index = indexFor(hash, table.length);
120         Entry<K, V> e = table[index];
121         while (e != null) {
122             if (e.key.hashCode() == k.hashCode()
123                     && (e.key == k || (k != null && k.equals(e.key)))) {
124                 return e.value;
125             }
126             e = e.next;
127         }
128         return null;
129     }
130 
131     static class Entry<K, V> {
132         K key;
133         V value;
134         Entry<K, V> next;
135         int hash;
136 
137         public Entry(K k, V v, Entry<K, V> n) {
138             key = k;
139             value = v;
140             next = n;
141             // hash = h;
142         }
143 
144         public V setValue(V v) {
145             V oldValue = value;
146             value = v;
147             return oldValue;
148         }
149 
150         public boolean equals(Object o) {
151             if (!(o instanceof MyHashMap.Entry)) {
152                 return false;
153             }
154             Entry e = (Entry) o;
155             Object k1 = e.key;
156             Object k2 = key;
157             if (k1 == k2 || (k1 != null && k1.equals(k2))) {
158                 Object v1 = e.value;
159                 Object v2 = value;
160                 if (v1 == v2 || (v1 != v2 && v2.equals(v2))) {
161                     return true;
162                 }
163             }
164             return false;
165         }
166     }
167 }

 

 

posted @ 2013-08-14 15:56  infinityu  阅读(231)  评论(0编辑  收藏  举报