jdk1.8 HashMap源码分析(put函数)
来源:互联网 发布:熟悉掌握办公软件 编辑:程序博客网 时间:2024/05/29 11:00
/** 将一个key和一个value在这个map中关联起来。 * Associates the specified value with the specified key in this map. 如果这个map中已经存在该key则会被替换。 * 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) { //会对key进行再一次的hash return putVal(hash(key), key, value, false, true);}/** * Computes key.hashCode() and spreads (XORs) higher bits of hash * to lower. Because the table uses power-of-two masking, sets of * hashes that vary only in bits above the current mask will * always collide. (Among known examples are sets of Float keys * holding consecutive whole numbers in small tables.) So we * apply a transform that spreads the impact of higher bits * downward. There is a tradeoff between speed, utility, and * quality of bit-spreading. Because many common sets of hashes * are already reasonably distributed (so don't benefit from * spreading), and because we use trees to handle large sets of * collisions in bins, we just XOR some shifted bits in the * cheapest possible way to reduce systematic lossage, as well as * to incorporate impact of the highest bits that would otherwise * never be used in index calculations because of table bounds. */static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}/** * Implements Map.put and related methods * * @param hash hash for key * @param key the key * @param value the value to put * @param onlyIfAbsent if true, don't change existing value * @param evict if false, the table is in creation mode. * @return previous value, or null if none */final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node<K,V>[] tab; Node<K,V> p; int n, i; //如果是第一次put,那么将会进行resize,n则为新容量, //如果不是第一次put,那么n = tab.length将得到原始的容量 if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; //i = (n - 1) & hash将会得到该元素在tab数组中的位置并赋值给i //此时p的值为tab[i]的元素 //如果tab[i]没有值,那么直接放置 if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); else { //如果存在值,那么就要考虑是不是hash冲突了 Node<K,V> e; K k; /* 如果两个冲突的元素hash值相等,并且key也一样, 将p赋值给e,后面会将value赋值给e.value, 这样就完成了相同key则使用新值覆盖原来的值, 这不是hash冲突,是因为用户put了多次相同的key */ if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; //后面的判断情况: //1、put的key和map中的key是不相同的,需要处理hash冲突 //2、key存在于p节点的链表中,那么将其value替换为上面传入的参数value else if (p instanceof TreeNode) //如果已经转化为红黑树了 //(hash冲突比较严重就会转化为红黑树),那么值直接添加节点 e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); else { //此时还没有转化红黑树,那么就添加链表中 //或者此时已经到了转化红黑树的邻界点了 for (int binCount = 0; ; ++binCount) { //如果当前节点没有下一个元素了,那么就添加上去 if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); //如果此时这个bin中的元素超过了TREEIFY_THRESHOLD(默认为8) //那么需要转化为红黑树 if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash); break; } //如果key存在于p节点的链表中, //那么将其value替换为上面传入的参数value if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } //这里就是替换value的工作 if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; //增加元素结束之后,size加一,并判断是否超过了需要扩容的临界值 //这里是HashMap一个小的瑕疵,总是在添加完元素之后再判断扩容, //如果扩容完之后再也不添加元素了,那么就会造成相当大的空间浪费 if (++size > threshold) resize(); afterNodeInsertion(evict); return null;}
阅读全文
1 0
- jdk1.8 HashMap源码分析(put函数)
- JDK1.8 HashMap中put源码分析
- jdk1.8 HashMap源码分析(构造函数)
- jdk1.8 HashMap源码分析(resize函数)
- HashMap源码分析(jdk1.8)
- 【Java】HashMap源码分析(JDK1.8)
- JDK1.8 HashMap源码分析
- JDK1.8 HashMap源码分析
- 【jdk1.8】HashMap源码分析
- jdk1.8 hashMap源码分析
- JDK1.8 HashMap 源码分析
- JDK1.8 HashMap源码分析
- HashMap源码分析 JDK1.8
- jdk1.8 HashMap源码分析
- java集合(4):HashMap源码分析(jdk1.8)
- HashMap源码分析——JDK1.8
- JDK1.8的HashMap源码分析
- Java源码分析之HashMap(JDK1.8)
- JAVA 类与对象
- 公钥和私钥
- Android 扩大ImageView的点击区域,解决按钮有效区域小的问题
- kafka->spark->streaming->mysql(scala)实时数据处理示例
- JAVA程序员必看的15本书
- jdk1.8 HashMap源码分析(put函数)
- MapReduce编程模型及优化技巧
- Python之操作XML文件
- java8 自定义TemporalAdjuster
- Window下 Qt 编译MySQL驱动
- 链表各类操作详解(讲得非常详细)
- ALTER TABLE ADD 增加多个字段 外键约束
- 数据库事务
- jdk1.8 HashMap源码分析(构造函数)