- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
java.util.concurrent.ConcurrentHashMap的构造方法之一:
public ConcurrentHashMap(int initialCapacity) {
if (initialCapacity < 0)
throw new IllegalArgumentException();
int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?
MAXIMUM_CAPACITY :
tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));
this.sizeCtl = cap;
}
方法“tableSizeFor(...)”的参数是什么意思?
initialCapacity + (initialCapacity >>> 1) + 1
我认为参数应该是这样的:
(int)(1.0 + (long)initialCapacity / LOAD_FACTOR)
或者只是:
initialCapacity
我认为参数表达式是错误的,至少是一个错误。我是不是理解错了什么?
我向 OpenJDK 发送了一个错误报告,他们似乎正式确认这很可能是一个错误:https://bugs.openjdk.java.net/browse/JDK-8202422
更新:Doug Lea 评论了这个错误,似乎他同意这是一个错误。
最佳答案
我强烈认为这是一种优化技巧。
您的想法是正确的。您引用的构造函数使用默认加载因子 0.75,因此要容纳 initialCapacity
元素,哈希表大小至少需要为
initialCapacity / 0.75
(大致等于乘以 1.3333333333)。然而浮点除法是昂贵的(一点点,还不错)。而且我们还需要四舍五入为整数。我想整数除法已经有所帮助
(initialCapacity * 4 + 2) / 3
(+ 2
用于确保结果向上舍入;* 4
应该很便宜,因为它可以实现为左移)。实现者做得更好:轮类比分类成本低得多。
initialCapacity + (initialCapacity >>> 1) + 1
这实际上是乘以 1.5,所以给我们的结果通常会比需要的大,但速度很快。 + 1
是为了补偿“乘法”四舍五入这一事实。
详情:>>>
是一个无符号右移,最左边补零。已经知道 initialCapacity
是非负的,这得到与除以 2 相同的结果,忽略余数。
编辑:我可能会补充说 tableSizeFor
四舍五入到 2 的幂,因此即使第一次计算给出的结果略大于所需的结果,最终结果通常也是 2 的幂.例如,如果您要求容量为 10 个元素(为了简化计算),表大小为 14 就足够了,公式得出 16。但是 14 会四舍五入为 2 的幂,所以我们还是得到 16 ,所以最后没有区别。如果您要求为 12 个元素留出空间,大小 16 仍然足够,但公式得出 19,然后四舍五入为 32。这是更不寻常的情况。
进一步编辑:感谢您在评论中指出您已将此作为 JDK 错误提交并提供链接:https://bugs.openjdk.java.net/browse/JDK-8202422 . Marin Buchholz 的第一条评论同意你的观点:
Yes, there is a bug here. The one-arg constructor effectively uses a load-factor of 2/3, not the documented default of 3/4…
我自己不会认为这是一个错误,除非您将其视为一个错误,您偶尔会获得比您要求的更大的容量。另一方面,你是对的,当然(在你的典型简洁错误报告中)存在不一致:你会期望 new ConcurrentHashMap(22)
和 new ConcurrentHashMap(22, 0.75f , 1)
给出相同的结果,因为后者只给出记录的默认加载因子/表密度;但是你得到的表格大小是前者的 64 和后者的 32。
关于java - 漏洞 : parameter 'initialCapacity' of ConcurrentHashMap's construct method?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50083966/
我最初构造了一系列嵌套的 ConcurrentHashMaps private final ConcurrentHashMap allInOne = new ConcurrentHashMap
我正在尝试使用 ConcurrentHashMap 初始化 ConcurrentHashMap private final ConcurrentHashMap > myMulitiConcurrent
为了提高工作效率,我尝试将数据保存在一个动态容器中。 我在 class 中初始化它与 private final ConcurrentHashMap allInOne = new Concur
我正在创建基于 Socket 的服务器-客户端预订服务,并且遇到有关将由多个线程访问的类的问题,是否需要扩展 ConcurrentHashMap 或创建变量 ConcurrentHashMap 是否足
从 Javadoc 我知道 ConcurrentHashMap.replace 是原子的,但是 ConcurrentHashMap.put 呢?我看到它们在源代码中的实现方式不同,但我无法弄清楚它们的
是 ConcurrentHashMap.get() 保证看到以前的ConcurrentHashMap.put()通过不同的线程?我的期望是,阅读 JavaDocs 似乎表明了这一点,但我 99% 确信
使用 ConcurrentHashMap,我发现 computeIfAbsent 比 putIfAbsent 慢两倍。这里是简单的测试: import java.util.ArrayList; imp
我有一个以下格式的 ConcurrentHashMap: ConcurrentHashMap> 现在在此 map 中,我想删除数组列表中的特定值。任何人都可以指导这一点。 编辑1:我有一张 map >
为什么 ConcurrentHashMap.Segment 和 ConcurrentHashMap.HashEntry 类是静态的?为什么要这样设计? 最佳答案 基本上所有不需要使用其封闭类属性的内部
在 ConcurrentHashMap 中通过键递增并发计数器时,使用常规 Int 作为值是否安全,还是我们必须使用 AtomicInteger?例如考虑以下两个实现 ConcurrentHashMa
我对java中的并发数据结构有疑问,特别是: 1) ConcurrentHashMap 2) HashMap 3) ConcurrentHashMap 如果我理解正确的话: 1) 读/写是线程安全的,
我正在尝试查看实际的 Java 文档,描述传递给 ConcurrentHashMap.computeIfAbsent 和 ConcurrentHashMap.computeIfPresent< 时可以
我有一个名为 SerializableL 的接口(interface)由 3 个不同的类实现: 产品 横幅 标签 我开始重构,想用多个方法调用替换多个段落。 public void load(Conc
一 JDK 中的 ConcurrentHashMap 在 JDK 8以前,HashMap 是基于数组 + 链表来实现的。整体上看,HashMap 是一个数组,但每个数组元素又是一张链表。 当向 Has
我想知道当我们在调整大小时尝试读取 ConcurrentHashMap 时可能发生的情况。 我知道在读取期间,第一次尝试总是不同步的。在第二次尝试中,它将尝试获取锁并重试。 但是,如果它在调整大小时发
在一个应用程序中,1 个线程负责不断更新映射,主线程定期读取映射,使用 ConcurrentHashmap 是否足够?或者我应该明确地锁定同步块(synchronized block)中的操作吗?任何
介绍 ConcurrentHashMap 技术是为了解决问题而生的,ConcurrentHashMap 解决了多个线程同时操作一个 HashMap 时,可能出现的内部问题。当多个线程同时操作一
我有一个由多个线程访问的键值映射: private final ConcurrentMap key_vval_map = new ConcurrentHashMap(); 我的自定义 get() 和
谁能告诉我这段代码出了什么问题?我要拔头发了! 如果我使用 HashMap 而不是 ConcurrentHashMap 则没有任何问题。代码使用JDK 5.0编译 public class MapTe
来自 ConcurrentHashMap 的源码 /** 171 * Number of unsynchronized retries in size and containsVal
我是一名优秀的程序员,十分优秀!