首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

java急需关注的知识点-HashMap

2012-09-10 
java需要关注的知识点---HashMap做了两年的java,感觉技术上没多大提升,特别是呆了一年外企,整理感觉自己都

java需要关注的知识点---HashMap

做了两年的java,感觉技术上没多大提升,特别是呆了一年外企,整理感觉自己都萎靡,不爱学习!
所以,写个帖子记下在网上看到的东西以及自己要去学习的内容!
努力奋斗!
1.HashMap的实现--------------------<在看>
?? 1.1 HashMap 的默认size是16,默认临界值是 12,默认的基数0.75。
?? 1.2 HashMap 的最大size是1<<30
?? 1.3 HashMap 中 transfer方法理解:

????????
           void transfer(Entry[] newTable) {        Entry[] src = table;        int newCapacity = newTable.length;        for (int j = 0; j < src.length; j++) {            Entry<K,V> e = src[j];//标记1            if (e != null) {                src[j] = null;//标记2                do {                    Entry<K,V> next = e.next;//标记3                    int i = indexFor(e.hash, newCapacity);//标记4                    e.next = newTable[i];//标记5                    newTable[i] = e;//标记6                    e = next;//标记7                } while (e != null);            }        }    }


??? 标记1:从Entry 数组中获取到 oldTable中需要往newTable 插入的entry实例e。
??? 标记2:回收oldTable的内存。
??? 标记3:使用临时变量存储e.next的值,以便下次获取链表的下个需要遍历的值,直到e.next的值为空。
??? 标记4:根据e的hash值和新表中的容量计算e需要放置在新数组中的index值。
??? 标记5:把新数组index位置的值传递给e.next.
??? 标记6:把e放置在新数组index的位置下。
??? 标记7:重新设置e的值,把老数组e的next值传递给e.继续下一轮循环,直到e的next为空。


?? 1.4 HashMap 中 put 方法:

??
 public V put(K key, V value) {        if (key == null)            return putForNullKey(value);        //根据hash算法获取需要插入数据的hash值        int hash = hash(key.hashCode());        //根据hash值,计算将要插入数组的index值        int i = indexFor(hash, table.length);        //如果该index下,存在链表值,遍历该链表,对比        //链表中的每一个entry的实例的hash值和key        //是否和需要插入的key和key的hash值相同。        //如果相同:跟新原entry下的value;保持key,index和hash值不        //变。        //如果不相同:把新纪录插入到数组中。        for (Entry<K,V> e = table[i]; e != null; e = e.next) {            Object k;            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {                V oldValue = e.value;                e.value = value;                e.recordAccess(this);                return oldValue;            }        }        modCount++;        addEntry(hash, key, value, i);        return null;    }   


?? 1.5 HashMap中的addEntry方法:

   void addEntry(int hash, K key, V value, int bucketIndex) {Entry<K,V> e = table[bucketIndex];        table[bucketIndex] = new Entry<K,V>(hash, key, value, e);        //如果数组table的长度大于临界值,将table进行扩容,长度为原来的        //两倍。        if (size++ >= threshold)            resize(2 * table.length);    }


??? 1.6 HashMap中的静态内部类Entry:

 static class Entry<K,V> implements Map.Entry<K,V> {        final K key;        V value;        Entry<K,V> next;        final int hash;        /**         * h:新创建的entry实例的hash值。         * k:键值         * v:值         * n:链表中但前entry实例的下一个entry的值。         */        Entry(int h, K k, V v, Entry<K,V> n) {            value = v;            next = n;            key = k;            hash = h;        }        public final K getKey() {            return key;        }        public final V getValue() {            return value;        }        public final V setValue(V newValue) {    V oldValue = value;            value = newValue;            return oldValue;        }        public final boolean equals(Object o) {            if (!(o instanceof Map.Entry))                return false;            Map.Entry e = (Map.Entry)o;            Object k1 = getKey();            Object k2 = e.getKey();            if (k1 == k2 || (k1 != null && k1.equals(k2))) {                Object v1 = getValue();                Object v2 = e.getValue();                if (v1 == v2 || (v1 != null && v1.equals(v2)))                    return true;            }            return false;        }        public final int hashCode() {            return (key==null   ? 0 : key.hashCode()) ^                   (value==null ? 0 : value.hashCode());        }        public final String toString() {            return getKey() + "=" + getValue();        }          void recordAccess(HashMap<K,V> m) {        }        void recordRemoval(HashMap<K,V> m) {        }    }


??? 1.7 HashMap中的remove()方法:

final Entry<K,V> removeEntryForKey(Object key) {        //获取hash值,如果key是null,hash值为0.        int hash = (key == null) ? 0 : hash(key.hashCode());        //获取该key的下标值。        int i = indexFor(hash, table.length);        Entry<K,V> prev = table[i];        Entry<K,V> e = prev;        while (e != null) {            Entry<K,V> next = e.next;            Object k;            if (e.hash == hash &&                ((k = e.key) == key || (key != null && key.equals(k)))) {                modCount++;                size--;                if (prev == e)                  //移动数组,用需要删除数组后一位置的值覆盖当前位置                    table[i] = next;                else                       //把需要删除的值,用当前链表中的下一个值                //进行覆盖,依次用下一个覆盖上一个,直到                //需要删除纪录后的每一数据都向前移动一位。                    prev.next = next;                e.recordRemoval(this);                return e;            }            prev = e;            e = next;        }        return e;    }


有代码可得知:hashmap的删除不知是单单的把需要删除的纪录内存释放(设置为null)。而是
移动需要删除纪录后的每一个元素来覆盖前元素,释放最后一个值。
??? 1.8 HashMap 中的get()方法:

   public V get(Object key) {        if (key == null)            return getForNullKey();        int hash = hash(key.hashCode());        for (Entry<K,V> e = table[indexFor(hash, table.length)];             e != null;             e = e.next) {            Object k;            if (e.hash == hash && ((k = e.key) == key || key.equals(k)))                return e.value;        }        return null;    }


从上面代码可以得知,当key为空的时候,hashmap从table[0]的位置获取专门存取null键的位置获取值,key不为空的时候,根据传入key的hash值,获取index值(数组下标),然后 遍历该index下的entry链表,比对该hash值下所有的key,如果有key和传入的key相同,
获取该key下的value.
??? 1.9 HashMap的结构图(见附件)
[img]
java急需关注的知识点-HashMap
?[/img]

?

热点排行