1、定义
public interface Map<K,V> { int size(); boolean isEmpty(); boolean containsKey(Object key); boolean containsValue(Object value); V get(Object key); V put(K key, V value); V remove(Object key); void putAll(Map<? extends K, ? extends V> m); void clear(); Set<K> keySet(); Collection<V> values(); Set<Map.Entry<K, V>> entrySet(); interface Entry<K,V> { V getValue(); V setValue(V value); boolean equals(Object o); int hashCode(); } boolean equals(Object o); int hashCode(); }
hash是“散列”:hash就是通过散列算法,将一个任意长度关键字转换为一个固定长度的散列值,但是有一点要指出的是,不同的关键字可能会散列出相同的散列值
2、HashMap类
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
3.底层存储
// 默认初始容量为16,必须为2的n次幂 static final int DEFAULT_INITIAL_CAPACITY = 16; // 最大容量为2的30次方 static final int MAXIMUM_CAPACITY = 1 << 30; // 默认加载因子为0.75f static final float DEFAULT_LOAD_FACTOR = 0.75f; // Entry数组,长度必须为2的n次幂 transient Entry[] table; // 已存储元素的数量 transient int size ; // 下次扩容的临界值,size>=threshold就会扩容,threshold等于capacity*load factor int threshold; // 加载因子 final float loadFactor ;
Entry数组
static class Entry<K,V> implements Map.Entry<K,V> { final K key ; V value; Entry<K,V> next; // 指向下一个节点 final int hash; 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(); } // 当向HashMap中添加元素的时候调用这个方法,这里没有实现是供子类回调用 void recordAccess(HashMap<K,V> m) { } // 当从HashMap中删除元素的时候调动这个方法 ,这里没有实现是供子类回调用 void recordRemoval(HashMap<K,V> m) { } }
HashMap采用将相同的散列值存储到一个链表中,也就是说在一个链表中的元素他们的散列值绝对是相同的。
4.构造方法
private void putAllForCreate(Map<? extends K, ? extends V> m) { for(Iterator<?extendsMap.Entry<?extendsK, ?extendsV>> i = m.entrySet().iterator(); i.hasNext(); ) { Map.Entry<? extends K, ? extends V> e = i.next(); putForCreate(e.getKey(), e.getValue()); } } /** * This method is used instead of put by constructors and * pseudoconstructors (clone, readObject). It does not resize the table, * check for comodification, etc. It calls createEntry rather than * addEntry. */ private void putForCreate(K key, V value) { int hash = (key == null) ? 0 : 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 != null && key.equals(k)))) { e. value = value; return; } } createEntry(hash, key, value, i); } void createEntry(int hash, K key, V value, int bucketIndex) { Entry<K,V> e = table[bucketIndex]; table[bucketIndex] = new Entry<K,V>(hash, key, value, e); size++; }
5、增加
public V put(K key, V value) { // 如果key为null,调用putForNullKey方法进行存储 if (key == null) return putForNullKey(value); // 使用key的hashCode计算key对应的hash值 int hash = hash(key.hashCode()); // 通过key的hash值查找在数组中的index位置 int i = indexFor(hash, table.length ); // 取出数组index位置的链表,遍历链表找查看是有已经存在相同的key for (Entry<K,V> e = table [i]; e != null; e = e. next) { Object k; // 通过对比hash值、key判断是否已经存在相同的key if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { // 如果存在,取出当前key对应的value,供返回 V oldValue = e. value; // 用新value替换之旧的value e. value = value; e.recordAccess( this); // 返回旧value,退出方法 return oldValue; } } // 如果不存在相同的key // 修改版本+1 modCount++; // 在数组i位置处添加一个新的链表节点 addEntry(hash, key, value, i); // 没有相同key的情况,返回null return null; } private V putForNullKey(V value) { // 取出数组第1个位置(下标等于0)的节点,如果存在则覆盖不存在则新增,和上面的put一样不多讲, 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++; // 如果key等于null,则hash值等于0 addEntry(0, null, value, 0); return null; }
hash函数
原文地址:https://www.cnblogs.com/L-a-u-r-a/p/8520002.html
时间: 2024-11-12 10:05:57