【发布时间】:2019-03-11 07:12:34
【问题描述】:
代码胜于雄辩,所以:
final int size = 100;
Map<Integer, String> m = new HashMap<>(size);
for (int i = 0; i < size; i++) m.put(i, String.valueOf(i));
为什么 HashMap 在内部调用 resize() 212 次!(感谢 Andreas 确定 JVM 在内部使用 HashMap,其中 19 21 cals 来自其他进程)
我的应用程序仍然不能接受两次resize() 调用。我需要对此进行优化。
如果我是一个新的 Java 开发人员,我对 HashMap 构造函数中“容量”的第一个直观猜测是,它是我(HashMap 的消费者)要放入的元素数量的容量。地图。但事实并非如此。
如果我想优化我对 HashMap 的使用,使其根本不需要调整自身大小,那么我需要足够深入地了解 HashMap 的内部结构,以准确了解 HashMap 存储桶数组需要有多稀疏。在我看来,这很奇怪。 HashMap 应该为您隐式执行此操作。这是 OOP 中封装的重点。
注意:我已经确认 resize() 是我的应用程序用例的瓶颈,所以我的目标是减少对 resize() 的调用次数。
问题:
如果我事先知道要放入地图的条目的确切数量。我选择什么容量来防止 任何 额外调用 resize() 操作?像size * 10 这样的东西?我还想了解一下为什么HashMap 是这样设计的。
编辑:我被问了很多为什么这种优化是必要的。我的应用程序在 hashmap.resize() 中花费了大量的 CPU 时间。我的应用程序使用的 hashmap 的初始化容量等于我们放入其中的元素数量。因此,如果我们可以减少 resize() 调用(通过选择更好的初始容量),那么我的应用程序性能就会提高。
【问题讨论】:
-
HashMap应该只需要调整一次大小,从初始容量 128 到最终容量 256。您如何衡量在代码执行期间它调整大小的次数? -
在执行这段特定代码的过程中,您如何计算对
resize()的 21 次调用仍不清楚。仅编译代码肯定不会显示循环导致实际HashMap对象调整大小的次数。你用什么方法来计算调整大小的实际次数? -
被调用2次有什么问题? first = 第一次创作;第二 = 因为加载因子 0.75 - 如果您知道有多少元素,请将加载因子更改为 1.0(或将元素数量除以加载因子以获得初始容量)
-
如果您不希望它调整大小两次(技术上一次),那么要么指定更大的初始大小(~134),要么使用更高的负载因子创建它,顺便说一句,这是如果不仔细考虑其文档中的描述,您不应进行调整。
-
而且你不需要深入了解内部,你只需要阅读 API 文档。这种行为是其契约的一部分,它不仅仅是一个实现细节。
标签: java optimization data-structures hashmap cpu