-
精细结构常数的量子重力预测
2020-04-19 19:14:07重力和物质波动之间的平衡导致了液力偶合器运行的固定点。 随着跨普朗克制中动量尺度的降低,逼近了它,从而导致了普朗克尺度上的轨距耦合的唯一预测值。 预测的精细结构常数的精确值取决于整体模型的物质含量。 它... -
计算复杂性:现代方法.[美]桑杰夫·阿罗拉(Sanjeev Arora)(带详细书签).pdf
2019-03-10 00:10:0314.5.2 与线性规模对数深度的线路之间的联系 246 14.5.3 与线路图之间的联系 246 14.5.4 卡奇梅尔维格德尔森通信游戏与深度下界 246 本章学习内容 248 本章注记和历史 249 习题 249 第15章 证明复杂性 251 ... -
论文研究 - 岩盐结构中硫化镁(MgS)的电子,输运和结构性质的预测
2020-05-26 16:31:34我们的计算与以前的其他ab-initio DFT计算之间的主要区别在于,我们在连续的自洽计算中使用了逐渐变大的基集来获得材料的基态。 对于室温晶格常数5.200Å,我们预测了3.278 eV的间接(Γ-X)带隙。 我们使用5.183Å... -
煤的吸附特性与表面能关系的实验研究
2020-05-03 19:47:22为建立煤的吸附特性与表面能的定量关系,利用悬滴法恒温27℃测试不同浓度下的APG(烷基糖苷)溶液表面张力,以及利用躺滴法测试临界胶束浓度下APG溶液在煤表面的平衡接触角,进而计算出煤的表面能。研究结果表明:APG溶液... -
来自移动源的空气在时间上的污染物传输
2020-06-05 01:33:53多层次的状态通量时空(SFST)方案带来了显着的计算加速,因为A-1仅需计算一次,例如在矿井通风情况下,即涉及具有恒定气流速度的长漂移的情况下。 在一个示例中显示了这种应用,该示例通过通风和移动的柴油装载机... -
论文研究 - 走向重力和光学的共同点
2020-05-25 19:18:49通过使用改进的卡文迪许天平的平衡输出对实验的证据进行足够长的观察,可以发现新的模式。 可以假设太阳具有旋转,进动和章动的圆环来解释这些模式。 本文的目的是介绍所有这些运动的频率。 圆环的旋转周期可以用来... -
论文研究 - 使用有限元方法轻松确定手机在脑组织中的辐射吸收
2020-05-21 11:42:43但是,它们与手持式移动设备发出的辐射之间的相互作用仍未完全了解。 这项研究旨在研究脑组织中的辐射吸收。 从小于1岁到大于10岁的牛脑组织是从专卖店(Sigma-Aldrich)购买的。 将组织在提取后72小时内用于离体脑... -
非交换BTZ黑洞的拟正规模和面积/熵的量化
2020-03-31 10:30:44我们研究了非交换BTZ黑洞的准正规模和面积/熵谱。 通过扩展视界半径中的非交换参数,可以给出QNM频率... 我们还发现耦合常数$$ \ xi $$ξ是标量场与引力场之间的耦合,它使QNM频率发生位移,但不影响面积/焓谱的结构。 -
热加速量子位:退相干,热化,长期增长和可靠的后期预测
2020-04-29 19:01:24对于自由场,我们将两者计算为量子位能级之间的差,无量纲量子位/场耦合常数,标量场质量和量子位的适当加速度的函数。 这两个时间尺度都不同于传统上为Unruh-DeWitt探测器计算的Candelas-Deutsch-Sciama跃迁速率,... -
双QFT中带电黑洞和迟滞的范德华式行为
2020-04-07 22:07:28使用AdS / CFT对应关系的规则,我们计算了剪切粘度的球形类似物,根据QFT的二元至五维带电广义相对论带负电荷... 势垒阻止了两个稳定状态之间的平衡路径。 系统演化必须通过亚稳定区域发生,并且产生路径依赖η〜/ s。 -
论文研究 - 流过一个球体
2020-05-22 09:47:29速度扰动离开球体的衰减率随教科书中距离的倒数立方而变化,此处计算出的衰减率很可能大不相同,并且取决于未知的常数函数,即曲率半径流线与距离球体的距离之间的关系。 如果从其他理论或详细观察(可能是条纹照片... -
单斜相HfO
2021-02-06 01:14:06用Jade5软件分析得到单斜相HfO2的晶格常数a,b,c以及晶格矢量a和c之间的夹角β。基于得到的晶格常数建立了单斜相HfO2薄膜的晶体结构模型。同时建立固态单斜相HfO2的晶体结构模型进行对比。通过密度泛函理论(DFT)... -
HashMap与ConcurrentHashMap简述
2020-10-24 15:27:47增删快:节点之间的链接断开,进行元素的增删,之后在链接上即可 查改慢:需要从链表头开始查。最大时间复杂度:T(m) = O(n);常数时间 0.3、红黑树 特点:接近于于平衡的二叉树。 相对于链表降低时间复杂度,T(n) =...版本:JDK1.8
针对put方法展开
0、两者底层数据结构
数组+链表+红黑树(JDK1.8新增)
0.1、数组
特点:查改快,增删慢。
查改快:通过数组下标定位 增删慢:增删会引起元素的移动
0.2、链表
特点:增删快,查改慢。
增删快:节点之间的链接断开,进行元素的增删,之后在链接上即可 查改慢:需要从链表头开始查。最大时间复杂度:T(m) = O(n);常数时间
0.3、红黑树
特点:接近于于平衡的二叉树。
相对于链表降低时间复杂度,T(n) = O(logn);对数时间,由于计算机使用二进制的记数系统,对数常常以2为底
引入红黑树的原因
1、解决发生哈希碰撞后,链表过长而导致索引效率的问题 2、利用红黑树增删改查快速的特点 3、时间复杂度有O(n)降为O(logn)
0.4、扩展
算法复杂度
算法复杂度分为时间复杂度和空间复杂度 时间复杂度是指执行这个算法所需要的计算工作量; 空间复杂度是指执行这个算法所需要的内存空间
1、两者整体区别
HashMap是线程不安全的,ConcurrentHashMap是线程安全的 HashMap的key和value可以为null,ConcurrentHashMap的key和value不可以为null
2、数组初始化
2.1、HashMap(线程不安全)
if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; //DEFAULT_INITIAL_CAPACITY = 1 << 4; //DEFAULT_LOAD_FACTOR = 0.75f; newCap = DEFAULT_INITIAL_CAPACITY; newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
默认数组初始化长度:16
加载因子:0.75f
默认扩容阀值:12
2.2、ConcurrentHashMap(线程安全)
if ((sc = sizeCtl) < 0) Thread.yield(); else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) { int n = (sc > 0) ? sc : DEFAULT_CAPACITY; Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n]; }
默认数组初始化长度:16
加载因子:0.75f
默认扩容阀值:12
线程安全体现
对数组初始化使用了CAS无锁化的方式保证了线程安全 CAS:Compare And Swap:比较并交换 数组初始化比较了内存中Node数组长度的值和当前线程中Node数组长度的值,默认都是0。 CAS操作将内存中数组的长度改为了-1,之后其他线程进来就会让出CPU执行权 然后当前线程就进行数组初始化操作
3、put操作和get操作
3.1、put操作之前
3.1.1、对key进行哈希散列计算
HashMap
hash(key); ================= static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); } ================= if ((p = tab[i = (n - 1) & hash]) == null)
ConcurrentHashMap
int hash = spread(key.hashCode()); =================== static final int spread(int h) { return (h ^ (h >>> 16)) & HASH_BITS; } =================== f = tabAt(tab, i = (n - 1) & hash)
哈希散列计算描述
进行哈希散列计算主要是为了确定元素的索引 为了保证数组的空间能得到充分的利用,需要考虑分散性、均匀性 两者底层hash算法会将key的hashCode值与数组的长度换算成32位二进制形式做位与运算 有一个前提和两个关键点 一个提前: 数组长度必须是2的次幂数 两个关键 1、得到一个整型数:key.hashCode() 该整型数很关键,关系到数组索引的分散性、均匀性,所以该整型数的最终运算结果要尽可能的不一样 2、控制这个整型数在0~length-1之间:key.hashCode()%length 将%运算换成&运算,key.hashCode()%length = key.hashCode()&(length - 1) 用位与运算替代取模的运算,位与效率更高 整型数最终会转化为32位二进制数形式的&(length-1)最终会得到一个索引index,确定Node节点存放的位置,10进制表示的范围 0~(length - 1) 索引index是由整型数和(length - 1)两个操作数决定的,所以最终还是取决于hash函数的结果 索引index还是要尽可能保证一样 在同一个数组中,length-1是固定的,所以索引index结果最终还是取决于整型数处理的最终结果,准确来说取决整型数的32位二进制数最后几位,因为高位不参与运算 即使整型数不同,但是二进制数形式表示的时候低位可能相同,参与运算结果还是有可能一样,因为只是低位参与运算 所以要保证最后几位不一样即可,因此用高16位和低16位进行异或(^)运算,重复的可能性减少,这样就更加保证了index不一样
3.2、HashMap(线程不安全)
put元素操作
索引处是否有值 没有值:直接put 有值: key相同:直接替换,返回旧值 key不同:形成链表或红黑树 链表:遍历链表,判断插入后链表长度是否达到8,JDK1.8之前是头插法 没有达到,尾插法。 达到,转为红黑树处理,判断哈希表中的容量(数组长度)是否达到最小树形化容量阈值64 当哈希表中的容量 > 该值时,才允许树形化链表 (即 将链表 转换成红黑树) 没有达到,进行数组扩容 达到,转红黑树 红黑树:直接put
get元素操作
public V get(Object key) { Node<K,V> e; //先通过hash(key)找到hash值,然后调用getNode(hash,key)找到节点 return (e = getNode(hash(key), key)) == null ? null : e.value; }
final Node<K,V> getNode(int hash, Object key) { Node<K,V>[] tab; Node<K,V> first, e; int n; K k; //通过(n - 1) & hash找到数组对应位置上的第一个node if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) { //如果这个node刚好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) { //如果是treeNode,就遍历红黑树找到对应node,最终会通过find方法 if (first instanceof TreeNode) return ((TreeNode<K,V>)first).getTreeNode(hash, key); //如果是链表,遍历链表找到对应node do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } while ((e = e.next) != null); } } //没有找到返回null return null; }
3.2、ConcurrentHashMap(线程安全)
put元素操作
索引处是否有值 没有值:直接put(CAS无锁化机制保证线程安全) 有值:使用同步代码块保证线程安全,将链表头或者红黑树根节点元素作为锁 key相同:直接替换,返回旧值 key不同:形成链表或红黑树 链表:遍历链表,判断插入后链表长度是否达到8(不在此同步锁),JDK1.8之前是头插法 没有达到,尾插法。 达到,转为红黑树处理(另一同步锁),判断哈希表中的容量(数组长度)是否达到最小树形化容量阈值64 当哈希表中的容量 > 该值时,才允许树形化链表 (即 将链表 转换成红黑树) 没有达到,进行数组扩容 达到,转红黑树 红黑树:直接put
get元素操作
public V get(Object key) { Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek; //先通过hash(key)找到hash值 int h = spread(key.hashCode()); if ((tab = table) != null && (n = tab.length) > 0 && (e = tabAt(tab, (n - 1) & h)) != null) { //如果这个node刚好key值相同,直接返回 if ((eh = e.hash) == h) { if ((ek = e.key) == key || (ek != null && key.equals(ek))) return e.val; } //如果不相同就再往下找 else if (eh < 0) //如果是treeNode,通过find方法中遍历红黑树找到对应node return (p = e.find(h, key)) != null ? p.val : null; //如果是链表,遍历链表找到对应node while ((e = e.next) != null) { if (e.hash == h && ((ek = e.key) == key || (ek != null && key.equals(ek)))) return e.val; } } //没有找到返回null return null; }
4、扩容
4.1、前置条件
每次put元素都会有判断,在每次put如果数组索引位置被使用都会有++操作,初始值是0,在数组初始化时会有一个扩容阀值:数组长度X加载因子
4.2、扩容条件
1、数组table被使用的容量超过扩容阀值 2、红黑树扩容:哈希表中的容量小于最小树形化容量阈值64(引起链表过长的根本原因是数组过短)
4.3、怎么扩容
长度和扩容阀值左移1位,变为原来容量的双倍
4.4、扩容与元素迁移
4.4.1、HashMap(线程不安全)
扩容说明:resize()方法 前置:判断扩容前哈希表是否为空,不为空则开始遍历数组 条件:数组索引处有元素 元素迁移 会重新计算hash值,得到新数组的index 1、没有链表或红黑树 直接搬运 2、有链表节点 遍历搬运 3、有红黑树节点 树形拆分搬运
4.4.2、ConcurrentHashMap(线程安全)
扩容说明: 在put元素的时候会进行头节点的hash值判断,如果等于MOVEN(也就是-1),就让当前线程帮助扩容(没有加锁,因为还需要其他线程帮助迁移元素,但是其他线程要能监测到当前线程正在扩容),在扩容的时候,会将这个hash值置为-1,相当于让其他线程监听到当前线程正在扩容,就去帮助当前线程进行扩容,会暂停线程put元素操作,等扩容完以后才能再put元素到新数组 addCount()判断是否需要扩容 transfer()方法 在此方法中,每个线程会领取任务 stride = MIN_TRANSFER_STRIDE;//最小16, //如果数组长度只有16,一个线程即可,多个的话下一个线程进来会领取自己对应的任务 搬运元素和HashMap一样,只是是用来同步代码块 前置:判断扩容前哈希表是否为空,不为空则开始遍历数组 条件:数组索引处有元素 元素迁移(同步代码块) 会重新计算hash值,得到新数组的index 1、没有链表或红黑树 直接搬运 2、有链表节点 遍历搬运 3、有红黑树节点 树形拆分搬运
5、问题
1、为什么要对key进行hash计算?
为了保证数组的空间能得到充分的利用,需要考虑分散性、均匀性
2、为什么数组初始化的长度要是2的指数次幂?
因为底层hash算法仍然要换算成二进制运算:hash%length=hash&(length-1) 如果不是2的次幂,就不等价hash%length!=hash&(length-1) 提升效率 即使传入非2的指数次幂的容量,在数组初始化时,也会将这个容量长度转换成最接近这个容量的2的n次方的数
3、加载因子为什么是0.75f?
如果设置为1,最大化利用空间,但是没办法达到理想状态,会导致链表过长或者红黑树时间复杂度增加 如果设置为0.5,查询效率高,节省时间,但是太浪费空间 空间利用率与时间复杂度上去择中,所以选择0.75
4、ConcurrentHashMap在put元素的时候有值情况下为什么不使用CAS无锁化机制保证线程安全?
因为有可能put很频繁,用CAS每次都要和内存中的作比较,非常不好。使用同步代码块,也就是数组上一个元素有一把锁,锁粒度变小,性能提高。
5、链表长度为什么阀值是8?
泊松分布算法
-
模拟电子技术学习资料
2010-01-05 09:15:55(1) 掌握比例、加减、积分、微分、对数和指数电路的工作原理及运算关系,能够运用“虚短”和“虚断”的概念分析各种运算电路输出电压与输入电压之间的运算关系,能够根据需要合理地选择电路。 (2) 正确理解LPF、... -
谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar
2013-06-13 22:35:213.7 各类数值型数据之间的混合运算 43 3.8 算术运算符和算术表达式 44 3.8.1 C运算符简介 44 3.8.2 算术运算符和算术表达式 45 3.9 赋值运算符和赋值表达式 47 33.10 逗号运算符和逗号表达式 48 3.11 小结 49 3.11.1... -
大话数据结构
2019-01-10 16:35:22现实中,人与人之间关系就非常复杂,比如我的认识的朋友,可能他们之间也互相认识,这就不是简单的一对一、一对多的关系了,那就是我们今天要研究的主题——图。 7.2.1各种图定义 214 7.2.2图的顶点与边间关系 217 ... -
大话数据结构 程杰
2018-09-01 10:06:43现实中,人与人之间关系就非常复杂,比如我的认识的朋友,可能他们之间也互相认识,这就不是简单的一对一、一对多的关系了,那就是我们今天要研究的主题——图。 7.2.1各种图定义 214 7.2.2图的顶点与边间关系 217 ... -
大话数据结构(中文高清版)
2017-04-19 11:57:097.2 图的定义 213 现实中,人与人之间关系就非常复杂,比如我的认识的朋友,可能他们之间也互相认识,这就不是简单的一对一、一对多的关系了,那就是我们今天要研究的主题--图。 7.2.1 各种图定义 214 7.2.2 图的... -
大话数据结构-程杰
2014-07-13 23:45:52现实中,人与人之间关系就非常复杂,比如我的认识的朋友,可能他们之间也互相认识,这就不是简单的一对一、一对多的关系了,那就是我们今天要研究的主题--图。 7.2.1 各种图定义 214 7.2.2 图的顶点与边间关系 217... -
大话数据结构三个版本
2018-09-10 09:39:38高斯在上小学的一天,老师要求每个学生都计算1+2+…+100的结果,谁先算出来谁先回家…… 2.4算法定义 20 现实世界中的算法千变万化,没有通用算法可以解决所有问题。甚至一个小问题,某个解决此类问题很优秀的算法却... -
《大话数据结构》( 程杰 编著)
2018-02-15 10:00:21现实中,人与人之间关系就非常复杂,比如我的认识的朋友,可能他们之间也互相认识,这就不是简单的一对一、一对多的关系了,那就是我们今天要研究的主题——图。 7.2.1各种图定义 214 7.2.2图的顶点与边间关系 217 ... -
A题:小鼠视觉感受区电位信号(LFP)与视觉刺激之间的关系研究 B题:机动目标的跟踪与反跟踪 C题:无线通信中的快时变信道建模 D题:人体营养健康角度的中国果蔬发展战略研究 E题:乘用车物流运输计划问题 2013年...
收藏数
23
精华内容
9
-
方剂解析查询软件.rar
-
sourceTree添加用户
-
基于信息分离和邻居惩罚选择的多目标优化
-
50 个 Redis 必备知识总结
-
双通14位AD转换芯片AD7366-7367开发板硬件参考设计+C源码软件DEMO例程+技术手册.zip
-
中文纠错工具简单词频统计
-
学习记录:selenium隐式等待与显示等待有什么不同
-
numpy-1.16.5-cp36-cp36m-win_amd64.whl
-
龙芯实训平台应用实战(希云)
-
Unity ILRuntime框架设计
-
Java 类的封装、继承、多态
-
cka认证最新练习题-cka-tasks.zip
-
Odoo Tree视图颜色组件,各行不同颜色
-
RFC3261-中文版本.zip
-
远离隐私泄露!17大安全工具保你上网无忧
-
2021-02-25
-
MHA 高可用 MySQL 架构与 Altas 读写分离
-
HTML5动态效果制作方法整理
-
BasicTraining总教程-2020.pdf
-
一个带下拉刷新列表的日历demo.zip