集合框架map学习笔记一HashMap

来源:互联网 发布:mysql linux 登录 编辑:程序博客网 时间:2024/05/16 06:48

Map: 

1、HashMap 

2、LinkedHashMap 

3、IdentityHashMap 

4、WeakHashMap 

5、TreeMap 

6、EnumMap 

7、ConcurrentHashMap 

8、ConcurrentSkipListMap 

今天主要学习的是HashMap。

1、HashMap

HashMap是根据key的HashCode值存储数据的,如果key的HashCode值冲突的时候,则以链表的形式逐个存放。具有很快的访问速度。但是正是因为这种存放机制,所以HashMap遍历里面的元素的时候,就是无序的。


1.1、HashMap的定义

往往我们使用HashMap的时候配置的参数采用默认配置,桶的容量为16,加载因子为0.75。

加载因子是指当HashMap的元素已经达到容量的75%的时候,就会进行扩充容器。

public HashMap() {        this.loadFactor = DEFAULT_LOAD_FACTOR;        threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);        table = new Entry[DEFAULT_INITIAL_CAPACITY];        init();    }


1.2、HashMap的存储

HashMap主要是调用put方法插入元素的。将Key的HashCode算出在table中的下标,如果此时Entry[] table对象的下标元素已经存在,则判断如果key和已经存在的key的hash值相同,且值或者对象相同的时候,则采用覆盖原则。如果不符合条件,则扩充桶位置的对象链表。

如果是null值,直接将值放在第一个。



/**     * Associates the specified value with the specified key in this map.     * If the map previously contained a mapping for the key, the old     * value is replaced.     *     * @param key key with which the specified value is to be associated     * @param value value to be associated with the specified key     * @return the previous value associated with <tt>key</tt>, or     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.     *         (A <tt>null</tt> return can also indicate that the map     *         previously associated <tt>null</tt> with <tt>key</tt>.)     */    public V put(K key, V value) {        if (key == null)            return putForNullKey(value);        int hash = hash(key.hashCode());        int i = indexFor(hash, table.length);        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;    }
/**     * Offloaded version of put for null keys     */    private V putForNullKey(V value) {        for (Entry<K,V> e = table[0]; e != null; e = e.next) {            if (e.key == null) {                V oldValue = e.value;                e.value = value;                e.recordAccess(this);                return oldValue;            }        }        modCount++;        addEntry(0, null, value, 0);        return null;    }

1.2、HashMap的取值

首先计算出key的HashCode值,所对应的桶的下标,然后逐个遍历桶下标对应链表的每个元素,对比出key所对应的结果。如果是null则直接取第一个。

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;    }    /**     * Offloaded version of get() to look up null keys.  Null keys map     * to index 0.  This null case is split out into separate methods     * for the sake of performance in the two most commonly used     * operations (get and put), but incorporated with conditionals in     * others.     */    private V getForNullKey() {        for (Entry<K,V> e = table[0]; e != null; e = e.next) {            if (e.key == null)                return e.value;        }        return null;    }

1.3、HashMap的遍历

HashMap中一般采用keySet或者采用entrySet进行元素的遍历。则采用的都是先遍历桶table的每个元素,当元素遍历到了以后内部采用链表遍历


private abstract class HashIterator<E> implements Iterator<E> {        Entry<K,V> next;// next entry to return        int expectedModCount;// For fast-fail        int index;// current slot        Entry<K,V> current;// current entry        HashIterator() {            expectedModCount = modCount;            if (size > 0) { // advance to first entry                Entry[] t = table;                while (index < t.length && (next = t[index++]) == null)                    ;            }        }        public final boolean hasNext() {            return next != null;        }        final Entry<K,V> nextEntry() {            if (modCount != expectedModCount)                throw new ConcurrentModificationException();            Entry<K,V> e = next;            if (e == null)                throw new NoSuchElementException();            if ((next = e.next) == null) {                Entry[] t = table;                while (index < t.length && (next = t[index++]) == null)                    ;            }    current = e;            return e;        }        public void remove() {            if (current == null)                throw new IllegalStateException();            if (modCount != expectedModCount)                throw new ConcurrentModificationException();            Object k = current.key;            current = null;            HashMap.this.removeEntryForKey(k);            expectedModCount = modCount;        }    }



原创粉丝点击