Java基础总结

来源:互联网 发布:秦安观点 网络强国 编辑:程序博客网 时间:2024/06/04 22:09
Java基础总结 - HashMap详解
这篇文章只是把大学记的笔记整理到博客,方便自己查看,不保证权威性(•̀ᴗ•́)و ̑̑
HashMap(内部构造了Entry内部类保存了k,v,以及前驱节点与后继节点):成员变量:   //默认的hash表数组大小    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16           //最大的hash表数组大小    static final int MAXIMUM_CAPACITY = 1 << 30;  //默认负载因子    static final float DEFAULT_LOAD_FACTOR = 0.75f;           //默认空hash表    static final Entry<?,?>[] EMPTY_TABLE = {};           //存值hash表    transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;           //hash表大小    transient int size;            //阈值    int threshold;           //负载因子    final float loadFactor;           //操作次数    transient int modCount;   //跟据容量算出来的一个值用来算存入对象hash    transient int hashSeed = 0;    static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;构造方法:public HashMap(int initialCapacity, float loadFactor) {if (initialCapacity < 0)    throw new IllegalArgumentException("Illegal initial capacity: " +                               initialCapacity);if (initialCapacity > MAXIMUM_CAPACITY)    initialCapacity = MAXIMUM_CAPACITY;if (loadFactor <= 0 || Float.isNaN(loadFactor))    throw new IllegalArgumentException("Illegal load factor: " +                               loadFactor);this.loadFactor = loadFactor;threshold = initialCapacity;init();    }    //指定容量以及默认的负载因子    public HashMap(int initialCapacity) {this(initialCapacity, DEFAULT_LOAD_FACTOR);    }   //默认负载容量以及负载因子    public HashMap() {this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);    }    public HashMap(Map<? extends K, ? extends V> m) {this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,      DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);inflateTable(threshold);putAllForCreate(m);    } 插入的时候:public V put(K key, V value) {//当hash表还是为空的时候if (table == EMPTY_TABLE) {    //填充hash表    inflateTable(threshold);                    -------> private void inflateTable(int toSize) {// Find a power of 2 >= toSize//hash表的大小都是2的倍数(因为用hash算在那个值得时候用到容量减一进行&操作,所以-1必须为基数)int capacity = roundUpToPowerOf2(toSize);//阈值等于hash表大小*容量因子,当大于阈值时就要扩容(有利于减少hash冲突)threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);table = new Entry[capacity];//通过容量算hash种子initHashSeedAsNeeded(capacity);}    }if (key == null)、//为空相当于下面散列到数组0位置    return putForNullKey(value);//通过hash散列int hash = hash(key);int i = indexFor(hash, table.length);//遍历对应的链表看是否存在该hash值存在就修改v的值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++;//不存在就创建一个Entry对象,放在对应链表头        addEntry(hash, key, value, i);--------> void addEntry(int hash, K key, V value, int bucketIndex) {//当hash表大小大于阈值时需要将hash扩大两倍,注意这里会造成put时锁死问题if ((size >= threshold) && (null != table[bucketIndex])) {    resize(2 * table.length);    hash = (null != key) ? hash(key) : 0;    bucketIndex = indexFor(hash, table.length);}createEntry(hash, key, value, bucketIndex);                              ----------->   //创建一个节点,插入对应桶链表的头位置 void createEntry(int hash, K key, V value, int bucketIndex) {Entry<K,V> e = table[bucketIndex];table[bucketIndex] = new Entry<>(hash, key, value, e);size++;    }    }        return null;    }