【发布时间】:2013-12-08 06:31:09
【问题描述】:
【问题讨论】:
-
阅读Wikipedia article on hash tables。它回答了你的问题。
-
谢谢大家!明白了。
标签: java performance collections hashmap hashcode
【问题讨论】:
标签: java performance collections hashmap hashcode
哈希码不必是唯一的,但如果不同的对象具有不同的哈希码,它们会更好地工作。
哈希码的一个常见用途是在HashMap 等数据结构中存储和查找对象。这些集合将对象存储在“桶”中,并且所存储对象的哈希码用于确定它存储在哪个桶中。这加快了检索速度。在查找对象时,HashMap 无需遍历所有对象,而是使用哈希码来确定要查找的存储桶,并且只查找该存储桶。
您询问了可变性。我认为您要问的是要求存储在HashMap 中的对象在地图中时不会发生突变,或者最好是该对象是不可变的。原因是,一般来说,改变一个对象会改变它的哈希码。如果一个对象存储在HashMap 中,它的哈希码将用于确定它被存储在哪个桶中。如果该对象发生了变异,它的哈希码就会改变。如果此时查找对象,则会产生不同的哈希码。这可能会将 HashMap 指向错误的存储桶,因此即使该对象之前存储在该 HashMap 中,也可能找不到该对象。
【讨论】:
哈希码不需要唯一,它们只是发生冲突的可能性非常低。
关于哈希码是不可变的,只有当对象将用作HashMap 中的键时才需要。哈希码告诉HashMap 在哪里对桶数组进行初始探测。如果键的哈希码发生变化,则映射将不再在正确的存储桶中查找,并且无法找到条目。
【讨论】:
hashcode() 基本上是一个将对象转换为数字的函数。在基于散列的集合的情况下,此数字用于帮助查找对象。如果这个数字发生变化,这意味着基于散列的集合可能错误地存储了对象,并且无法再检索它。
哈希值的唯一性允许在集合内部更均匀地分布对象,从而提高性能。如果所有内容都散列到相同的值(最坏的情况),性能可能会下降。
The wikipedia article on hash tables 提供了一个很好的读物,可能也有助于解释其中的一些内容。
【讨论】:
这与项目在哈希表中的存储方式有关。哈希表将使用元素的哈希码来存储和检索它。在这里完全解释有点复杂,但您可以通过阅读本节了解它:http://www.brpreiss.com/books/opus5/html/page206.html#SECTION009100000000000000000
【讨论】:
为什么通过散列搜索更快?
假设您有一些独特的对象作为值,并且您有一个 String 作为它们的键。每个键都应该是唯一的,以便在搜索键时,您可以找到它作为其值保存的相关对象。
现在假设您有 1000 个这样的键值对,您想要搜索特定键并检索其值。如果您没有散列,则需要将您的密钥与表中的所有条目进行比较并查找密钥。
但是使用散列,您可以散列您的密钥并将相应的对象放入某个桶中以插入。现在,当您要搜索特定键时,将对要搜索的键进行哈希处理并确定其哈希值。您可以直接进入该哈希桶,并选择您的对象,而无需搜索整个关键条目。
【讨论】:
hashCode 是一个棘手的方法。它应该提供平等的简写(这是地图和集合关心的)。如果您的地图中的许多对象共享相同的哈希码,则地图将不得不经常检查equals - 这通常会更昂贵。
检查equals 的javadoc - 即使对于不可变对象,该方法也很难正确处理,并且使用可变对象作为映射键只是在自找麻烦(因为该对象是为其“旧”哈希码存储的)
【讨论】:
只要您使用的是按索引 (0,1,2...collection.size()-1) 检索元素的集合,就不需要哈希码。但是,如果我们谈论的是像地图这样的关联集合,或者只是询问集合does it contain some elements,那么我们谈论的是昂贵的操作。
哈希码就像提供对象的摘要。它坚固而独特。哈希码通常用于二进制比较。比较每个集合成员的二进制级哈希码并不昂贵,因为通过它的属性比较每个对象(肯定超过 1 个操作)。哈希码需要像指纹一样 - 一个实体 - 一个,并且是不可变的哈希码。
【讨论】:
散列的基本思想是,如果在一个集合中查找一个对象,其散列码与该集合中 99% 的对象的散列码不同,则只需检查散列码匹配的 1% 的对象。如果哈希码与集合中 99.9% 的对象的哈希码不同,则只需检查 0.1% 的对象。在许多情况下,即使一个集合有一百万个对象,一个典型对象的哈希码也只会匹配其中的一小部分(在许多情况下,不到十几个)。因此,单个哈希计算可以消除近百万次比较的需要。
请注意,哈希值不必绝对唯一,但如果太多实例共享相同的哈希码,性能可能会非常糟糕。请注意,对性能重要的不是不同哈希值的总数,而是它们“聚集”的程度。在包含一百万个事物的集合中搜索一个对象,其中一半的项目都具有一个哈希值,而其余的每个项目都具有不同的值,平均需要检查大约 250,000 个项目。相比之下,如果有 100,000 个不同的哈希值,每个哈希值由 10 个项目返回,那么搜索一个对象将需要检查大约 5 个。
【讨论】:
您可以定义一个从 HashMap 扩展的自定义类。然后通过仅使用 equals 方法比较键和值来覆盖方法(get、put、remove、containsKey、containsValue)。然后添加一些构造函数。正确覆盖 hashcode 方法非常困难。
我希望我已经帮助了每个想要轻松使用 hashmap 的人。
【讨论】: