调试时我发现了一种奇怪的行为。
我有一个HashMap<Integer, Set<Term>>
(Term是一个只包含字符串的类),正常的toString()
显示了这个:
当我点击HashMap的table属性时,我得到了这个:
我现在的问题,为什么表toString()
中有空值?
编辑:感谢您的快速解答!如果可以的话,我会接受所有这些......
答案 0 :(得分:2)
因为您正在使用的Map实现正在使用一组HashBuckets,其中一些在开始时为NULL(由initialCapacity决定)。如果超过条目数,它将开始为对象创建更多HashBuckets / slots。将此视为HashMap自动为您创建的增长储备。
了解更多: https://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
答案 1 :(得分:2)
HashMap将其条目存储在哈希表中。这是一个数组,哈希函数将键映射到其中一个数组条目(也称为哈希桶)。
哈希桶总是至少20%为空。如果不是,则调整数组大小以确保有足够的可用空间。
原因是当哈希表被填满时,哈希之间的冲突越来越可能。如果碰撞太频繁,您将失去HashMap的所有优点。太满了,你的HashMap也不会比LinkedList好(是的,LinkedList,而不是ArrayList)。它可能会更糟。
答案 2 :(得分:2)
HashMap是一个Map实现,其关键特性是恒定时间O(1)查找。
计算机科学中具有恒定时间查找的唯一数据结构是固定长度的数组。当您初始化HashMap时,它会创建一个固定长度的数组,当您的条目超出当前数组的大小时,它将展开。
编辑:@kutschkem指出,当条目数大约是当前数组大小的80%时,java.util.HashMap会扩展其固定长度数组,而不是当条目超过当前数组时#& 39;尺寸。
答案 3 :(得分:1)
这就是哈希映射的工作原理:一个大型数组(table
),对于某些键,尝试了以下表项:
table[key.hashCode() % table.length]
然后使用该表槽。如果已存在不是equals(key)
的密钥,则使用重新散列。
因此,最初该表仅包含空值,并且大小为initialCapacity
。当哈希映射变得太满(loadFactor
)时,可以生成数组。
答案 4 :(得分:1)
HashMap在内部使用数组来存储条目。非常简化,它执行类似array_index = hashcode % array_length
的操作(再次:非常简化,因为它还需要处理哈希冲突等)。此内部数组通常大于您在HashMap中存储的元素数 - 否则,每次向其添加元素时都必须调整数组的大小。所以你看到的null
是数组中尚未使用的插槽。
答案 5 :(得分:1)
这是正常行为。
有空值,因为表数组已初始化为填充空值,并使用null表示该散列桶中没有存储值。
提供的toString()函数不会跳过它们,因为看到它们对调试HashMap实现的folds很有用。
如果你想看到没有空值的内容,你必须编写自己的显示函数,或者通过继承HashMap并重写toString()或者在你的代码中的某处提供一个便利函数。