【问题标题】:What are the differences between hashtable and hashmap? (Not specific to Java)hashtable和hashmap有什么区别? (不特定于 Java)
【发布时间】:2016-07-18 18:01:15
【问题描述】:

在我最近一次软件工程师职位的面试中,有人问我这个问题:hashtable 和 hashmap 之间有什么区别?我问面试官他是否具体了解 Java,因为在 Java 中 hashtable 是同步的,而 hashmap 不是(实际上有大量信息可以在谷歌搜索后比较 Java 中的 hashtable 与 hashmap,所以这不是我要寻找的答案),但他说不,并且想让我解释一下这两者的区别。

我对这个问题感到非常困惑和震惊(实际上现在仍然很困惑)。 IMO、hastable 或 hashmap 只是一个术语问题。实际上只有 Java 有这两个术语,而在 C++ 等其他语言中,它们甚至没有术语哈希表。面试的时候刚刚解释了hash的原理,说hashmap和hashtable都应该基于这个原理来实现,不知道这两者有没有区别。面试官肯定不服气,一直在寻找其他答案,当然我在那轮之后被拒绝了。

回到主题,hashmap 和 hashtable 之间可能有什么区别(不是 Java 特有的)?

【问题讨论】:

  • 跟进,看起来 C# 中的字典和哈希表之间存在差异,但这不是我想要的。

标签: hashmap hashtable


【解决方案1】:

在计算机科学中,由于措辞而有所不同。

HashTable 是某种查找表,它使用键散列在类似数据结构的表中查找相应的值。那只是一种键值映射。您可能知道有不同的实现。不同的哈希、哈希串通解决方案和表增长策略等等。仅当您出于某种原因需要制作自己的哈希表时才有意义。

HashMap 是键值对与散列键的某种映射。映射本身是抽象的,它可能不是表格。平衡树或尝试或其他数据结构/映射也是可能的。

您可以简化并说 HashTable 是底层数据结构,而 HashMap 可能正在使用 HashTable。

字典是另一个抽象级别,因为它可能根本不使用散列 - 例如使用全文二进制搜索查找或其他比较方式。这就是你在不考虑某些编程语言的情况下所能得到的全部内容。

-- 在想太多之前。你能肯定地说——你的面试官知道他/她在说什么吗?你讨论了技术细节还是他们只是听/问,有时评论?有时,面试官只是对他们一开始并不真正理解的问题提出最可笑的答案。 就像你自己写的一样,一般来说它只是术语。软件开发人员经常使用可互换的术语,但可能在 Java 中确实存在差异的人除外。

【讨论】:

  • 感谢您的回复。我认为您的回答非常好,但我现在还不能将其标记为正确答案。为了澄清事情,这个问题是一个没有任何背景的孤立问题,面试官只是把它扔给了我。另外,我非常有信心他没有提出这个问题,因为其他人提到了为同一家公司面试的这个问题。正如我在帖子中提到的,我向他解释了哈希的原理,并说 hashtable 和 hashmap 都可以这样实现(我知道你也可以使用二叉搜索树来实现 hasmap,但我没有提到)......
  • (继续)并询问面试官是否可以就他正在寻找的答案给我任何提示。他没有给我任何暗示,而是问了我另一个问题。我对结果感到非常失望,因为我采访的公司是同行业中享有盛誉的公司,他们是这样进行采访的。
  • 我明白了。 Here 是在普通数据结构级别上的另一个较旧的答案,this 在其答案中涵盖了更多内容。祝你好运找到你的答案。如果你能做的只是假设什么是正确的,或者有足够的复杂性/深度来作为答案,那就很难了。
  • 感谢您的链接。可能我不会找到更好的答案来回答这个问题,我会将您的答案标记为正确的答案。再次,我对这个问题感到非常失望。知道答案会让你成为更好的程序员吗?我怀疑。
  • 我也对此表示怀疑。我对面试官的评论来自经验(双方)。通常,您会从人力资源部或某些负责人那里得到想要具体答案的人,而这可能根本没有意义。有时他们会问一些奇怪的东西,想看看你在平衡时的反应。如果它一直困扰着您,请给他们写一封电子邮件/消息。征求反馈,表明你关心并在之后评估了面试。友善,简短,具体询问。最后,您可以向他们展示没有您他们会失去什么。 ;)
【解决方案2】:

面试官可能一直在寻找...

  • 哈希表是一个较低级别的概念,并不暗示或必然支持任何键和值的区别或分离(即您可以使用哈希表实现值的哈希set),而
  • hash map 必须支持不同的键和值,因为键和值之间存在映射/关联;两者是不同的,即使在某些实现中它们总是并排存储在内存中,例如相同结构的成员/std::pair<>

示例:(错误的)哈希表实现阻止用作哈希映射。

考虑:

template <typename T>
class Hash_Table
{
    ...
    bool insert(const T& t)
    {
        // work out which bucket t hashes to...
        size_t bucket = hash_bytes((void*)&t, sizeof t) % num_buckets_;

        // see if t is already stored in the bucket...
        if (memcmp((void*)&t, (void*)&buckets_[bucket], sizeof t) == 0)
            ...
        ... handle collisions etc. ...
    }
    ...
};

上面,对哈希函数的硬编码调用将插入的值视为二进制 blob,以及整个 tmemcmp,意味着您不能让 Tstd::pair&lt;int, std::string&gt;并将哈希表用作从ints 到strings 的哈希映射。所以,这是一个可用作哈希映射的哈希表示例。


可能会或可能不会也认为哈希表根本不提供任何方便的功能以用作哈希映射而不是哈希映射。例如,如果 API 的设计好像只处理值 - h.insert(t); h.erase(t); auto i = h.find(t); - 但它允许调用者指定任意自定义比较和散列函数,这些函数可能会将其操作限制为仅t,那么哈希表可以(ab)用作功能哈希映射。


为了澄清这与 makadev 现有答案的关系,我不同意:

  • "A HashTable [使用] key hashes 来查找对应的值";错误,因为它假定一个键->值映射。

  • “一个 HashMap [...]。映射本身是抽象的,它可能不是一个表。平衡树或尝试或其他数据结构/映射也是可能的。”;错误,因为哈希映射的主要机制仍然是对表/数组中存储桶(索引)的键进行哈希处理:一些哈希表/映射可能使用其他数据结构(数组、链表、树...)来存储元素在同一个桶中碰撞,但这是一个不同的问题,不是哈希表和哈希映射之间差异的一部分。

【讨论】:

  • 一个有效的观点,但又回到了“......这只是术语”这一点。你的 HashTable 不是我所说的the Data-structure HashTable。同样,您的 HashMap 并不是我所说的通过散列键进行抽象映射的意思,而是我所知道的 HashTable,除了“不暗示支持键和值的区分或分离”。顺便提一句。这对我来说实际上没有意义。为什么你想要一个像 HashTable 或 HashSet 这样没有区别的查找数据结构 - f.e.是否存在密钥检查?
  • @makadev:“这只是术语”——对数据结构、设计模式等有共同的理解。术语让我们能够简洁而有意义地描述和讨论系统。你编写的系统越多,其他人必须帮助维护、发展或使用,它就越重要。无论如何,“你为什么想要一个像 HashTable 或 HashSet 这样没有区别的查找数据结构 - fe 用于存在检查 - 键?” - 哈希集可能存储在文本文件中看到的单词:没有不同的键值与值 - 每个单词都是键 值。不说 word1 和 word2 没有区别。
【解决方案3】:

实际上 HashTable 已经过时了,而 HasHMap 是最好的使用方法,因为 Hashtable 是同步的。如果不需要线程安全的实现,建议使用 HashMap 代替 Hashtable。如果需要线程安全的高并发实现,那么建议使用 java.util.concurrent.ConcurrentHashMap 代替 Hashtable。

第二个区别是HashMap扩展了Map接口和HashSet字典接口。

【讨论】:

  • 问题说不是特定于java。
猜你喜欢
  • 2010-11-15
  • 2021-01-02
  • 2015-07-18
  • 2020-10-11
  • 1970-01-01
  • 2012-02-11
  • 2012-04-27
  • 2012-01-14
  • 1970-01-01
相关资源
最近更新 更多