Map的原理1.Map 是什么Map用于保留具备映射关系的数据,Map汇合里保留着两组值,一组用于保留Map的Key,另一组保留着Map的value。
Map有哪些办法
2.HsahMap 是什么HashMap 是一个采纳哈希表实现的键值对汇合,继承自 AbstractMap,实现了 Map 接口。
HashMap 的非凡存储构造使得在获取指定元素前须要通过哈希运算,失去指标元素在哈希表中的地位,而后再进行大量比拟即可失去元素,这使得 HashMap 的查找效率高。
当产生 哈希抵触(碰撞)的时候,HashMap 采纳 拉链法 进行解决,因而 HashMap 的底层实现是 数组+链表,如下图:
HashMap实现概述容许key/value为null,然而key只能有一个null非线程平安,多个线程同时操作同一个HashMap实例所做的批改在线程间不同步遍历时不保障任何程序,跟元素插入程序或者拜访程序无关进行遍历时如果执行HashMap的remove(Object key)或者put(Object value)办法时会疾速失败,抛出异样ConcurrentModificationException。遍历时删除元素只能通过Iterator自身的remove()办法实现HashMap中有两个重要概念因为 HashMap 扩容开销很大(须要创立新数组、从新哈希、调配等等),因而产生扩容相干的两个因素:
容量(capacity)HashMap以后长度负载因子(load factor)负载因子,默认值0.75f不利因素:容量太小扩容rehash,导致性能升高,加载因子太大则会发生冲突,查找的效率变低.
容量即该HashMap可能存储的最大的key个数,为便于扩容,容量都是2^n次方。负载因子用于计算执行扩容的阈值,默认的负载因子是0.75,该值是综合思考HashMap的get/put等多种操作时的工夫空间上的均衡,举荐应用默认值即可。如果容量时256,负载因子是0.75时,当key的总量超过192个时会进行扩容,即容量变成原来的两倍512,原有的存储的key会从新通过hash运算重新分配。常量// 如果不指定初值的话,列表的长度就为16,默认加载因子为0.75,static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16static final int MAXIMUM_CAPACITY = 1 << 30;static final float DEFAULT_LOAD_FACTOR = 0.75f;static final int TREEIFY_THRESHOLD = 8;static final int UNTREEIFY_THRESHOLD = 6;static final int MIN_TREEIFY_CAPACITY = 64;成员变量// node列表transient Node<K,V>[] table;// 缓存节点transient Set<Map.Entry<K,V>> entrySet;// 节点数量transient int size;// 批改的次数transient int modCount;// 极限值,如果节点数大于这个值就须要扩容,计算形式是capacity * loadfactorint threshold;// 加载因子,节点数值大于以后总数的肯定百分比时扩容final float loadFactor;HashMap 的实现形式/* ---------------- Public operations -------------- *//** * Constructs an empty <tt>HashMap</tt> with the specified initial * capacity and load factor. * * @param initialCapacity the initial capacity * @param loadFactor the load factor * @throws IllegalArgumentException if the initial capacity is negative * or the load factor is nonpositive */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; this.threshold = tableSizeFor(initialCapacity);}/** * Constructs an empty <tt>HashMap</tt> with the specified initial * capacity and the default load factor (0.75). * * @param initialCapacity the initial capacity. * @throws IllegalArgumentException if the initial capacity is negative. */public HashMap(int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR);}/** * Constructs an empty <tt>HashMap</tt> with the default initial capacity * (16) and the default load factor (0.75). */public HashMap() { this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted}public HashMap(Map<? extends K, ? extends V> m) { this.loadFactor = DEFAULT_LOAD_FACTOR; putMapEntries(m, false);}// Map中生成一个新的Map,属于深拷贝final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) { int s = m.size(); if (s > 0) { if (table == null) { // pre-size float ft = ((float)s / loadFactor) + 1.0F; int t = ((ft < (float)MAXIMUM_CAPACITY) ? (int)ft : MAXIMUM_CAPACITY); if (t > threshold) threshold = tableSizeFor(t); } else if (s > threshold) resize(); for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) { K key = e.getKey(); V value = e.getValue(); putVal(hash(key), key, value, false, evict); } }}get办法public V get(Object key) { Node<K,V> e; return (e = getNode(hash(key), key)) == null ? null : e.value;}/** * Implements Map.get and related methods. * * @param hash hash for key * @param key the key * @return the node, or null if none */final Node<K,V> getNode(int hash, Object key) { Node<K,V>[] tab; Node<K,V> first, e; int n; K k; // 列表是否为空 if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) { // 第一个是否要找的,判断条件统一且key统一 if (first.hash == hash && // always check first node ((k = first.key) == key || (key != null && key.equals(k)))) return first; if ((e = first.next) != null) { if (first instanceof TreeNode) return ((TreeNode<K,V>)first).getTreeNode(hash, key); // 依据哈希抵触解决办法,每个数据项都是一个链表,须要遍历这个链表去找到咱们须要的key那项 do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } while ((e = e.next) != null); } } return null;}put办法put操作时,HashMap会先进行初始化,如果没有先进行初始化操作,初始化过程会取比用户指定容量大的最近2的幂次数作为数组的初始容量,如果设置扩容的阀值也进行更新,初始化实现当前持续put办法。
...