Python中HashMap和Dictionary的区别

2025 年 3 月 4 日 | 阅读 15 分钟

如今,当数据从业者谈论数据存储时,他们通常指的是数据的位置,例如本地文件、云存储、SQL 或 NoSQL 数据库等。然而,数据如何保存也是数据存储的一个关键组成部分。

数据存储的机制通常发生在最低的层级,就在计算机语言的基础之上。它不是关注如何使用这些工具,而是关注数据从业者如何设计它们。然而,数据专业人员需要理解数据存储,才能掌握支持他们工作的底层机制。此外,有了这些知识,他们将能够做出更好的判断,从而提高计算机性能。

我们将在本文中讨论哈希映射。哈希映射是一种使用哈希算法关联存储信息的数据结构。哈希映射是经过优化以加快数据操作(例如搜索、插入和删除)的数据结构。

许多现代计算机语言都支持哈希映射,包括 PythonJavaC++。您无疑熟悉字典,这是一种常用于在 Python 中构建哈希映射的流行数据结构。后续部分将涵盖字典的基本原理、其操作方式以及如何使用各种 Python 包实现它们。

理解 HashMap

我们必须首先理解什么是哈希才能定义哈希映射。哈希方法涉及将每个给定的键或字符串字符更改为不同的值。通常,结果是一个固定长度的较短数字,比原始键更容易进行计算操作。

最流行的哈希实现之一是哈希映射,也称为哈希表。键值对(例如员工 ID 和员工姓名)存储在哈希映射中,并使用基于索引的列表进行访问。

哈希映射的工作原理是将条目或键/值对分布到多个桶中。哈希函数接受一个键并使用它来计算一个唯一索引,该索引指示项目可能位于何处。哈希映射特别适合各种数据操作,例如数据插入、删除和搜索,因为它们使用索引而不是原始键。

哈希函数根据数学哈希方法创建新值,以计算哈希值,或简称为哈希。由于键值对理论上没有限制,因此哈希算法将根据指定的表大小映射键。

有多种哈希函数可用,每种都有优缺点。哈希函数的主要目标是,给定相同的输入,始终返回相同的值。

最常见的哈希函数如下:

  • 除法法。此方法是获取哈希值最直接、最快速的方法。为此,将键除以表的大小,并将余数用作哈希。
  • 平方取中法。元素的索引将通过取中间数字并使用给定键的平方来确定。
  • 乘法法。哈希索引是通过将键乘以一个大的实数,并使用小数部分来确定的。
  • 折叠法。首先,将键切成等大小的部分。接下来,将结果求和并除以表的大小。余数就是哈希值。

Python 哈希映射

Python 使用其内置的字典数据类型来实现哈希映射。字典数据以 {key:value} 对的形式存储,就像哈希映射一样。一旦创建了字典(参考下一节),Python 将使用内置的便捷哈希函数计算每个键的哈希值。

Python 字典包含以下特征:

  • 字典可以更改。这意味着当字典生成时,我们可以编辑、添加或删除条目。
  • 组件具有固定的顺序。Python 3.6 及更早版本中的字典条目未排序;相反,它们是固定顺序的。然而,Python 3.7 发布后,字典开始保持顺序。现在,Python 字典中的键将按照源代码中指定的顺序创建。阅读 Python 主要开发者之一 Raymond Hettinger 的这条评论,了解此举背后的思想。
  • 键不可更改。因此,不可变数据类型始终用作键。换句话说,字典只接受可哈希数据类型,例如元组、字符串和整数。相反,键永远不能是可更改的数据类型,例如列表。
  • 键是唯一的。字典的键是唯一的,不能在字典内替换。如果多次使用,后续条目将替换以前的值。

因此,关于字典和哈希映射之间有什么区别的问题答案很简单。所有字典都是 Python 中原生实现的哈希映射。字典是一种特定类型的哈希映射,它基于 Python;其结构和操作由 Python dict 类定义。哈希映射是一种可以使用各种哈希算法构建的数据结构。

使用 Python 字典函数

让我们研究一些最常用的字典函数。有关如何使用字典的更多信息,请参阅我们的 Python 字典教程。

字典创建

在 Python 中,创建字典相当容易。您所要做的就是使用花括号输入键值对,用逗号分隔。或者,您可以使用内置的 dict() 函数。

  • 该函数生成 capital_countries,一个 Python 字典。
  • 在 Python 中,字典是一组键值对。
  • “Paris”、“Berlin”和“Rome”这些术语用作字典的键。
  • 与这些键对应的值是“France”、“Germany”和“Italy”。
  • 为了表示键和值是字符串,它们被包含在单引号中。
  • 花括号包含整个字典,冒号用于分隔键值对。

打印字典内容

  • capital_countries 变量的内容在 Python 代码的一行中打印。
  • 内置的 Python 方法 print() 用于将数据输出到控制台。
  • 预计 capital_countries 将是一个字典,这是一种预构建的 Python 数据类型,用于保存键值对。
  • 当运行此行代码时,整个字典 capital_countries 将被写入控制台。

输出

 
{'Paris': 'France', 'Berlin': 'Germany', 'Rome': 'Italy'}   

请务必记住,字典键必须是唯一的;不允许重复键。然而,Python 将简单地忽略重复键情况下的初始键值组合,并认为键的最新实例有效,而不是引发异常。请自行查看

  • 该代码定义了 capital_countries,一个 Python 字典。
  • 用花括号 {} 包裹的键值对构成一个字典。
  • 冒号 (:) 分隔每个键值对,逗号 (,) 分隔对。
  • 此字典的键是“Paris”、“Berlin”和“Rome”。
  • 匹配的值是“China”、“Germany”、“Italy”和“France”。
  • 键“Paris”出现两次,分别用“China”和“France”表示不同的值。
  • 在 Python 中,如果键在字典中出现多次,则保留提供给键的最新值。
  • 因此,最终字典将是 { 'Paris': 'France', 'Berlin': 'Germany', 'Rome': 'Italy' }。
  • capital_countries 变量的内容在 Python 代码的一行中打印。
  • 内置的 Python 方法 print() 用于将数据输出到控制台。
  • 预计 capital_countries 将是一个字典,这是一种预构建的 Python 数据类型,用于保存键值对。
  • 当运行此行代码时,整个字典 capital_countries 将被写入控制台。

输出

 
{'Paris': 'France', 'Berlin': 'Germany', 'Rome': 'Italy'}   

在字典中查找词条

为了进行字典搜索,我们必须在括号中输入键。Python 将返回相应的值,如下所示

上面的代码输出或数据输入是教程的补充。

输出

 
'France'   

如果您尝试访问字典中未列出的键,Python 将生成错误。您可以改用 .get() 函数来检索键以避免此情况。如果键不存在,它将简单地返回 None 值

输出

 
None   

修改和删除字典中的条目

应添加一个新的首都-国家对

  • 如上文所示,Python 字典是键值对的集合。
  • 冒号 (:) 分隔每对;键是“Paris”、“Rome”和“Madrid”,值是“China”、“Italy”和“United Kingdom”。
  • 花括号 ({}) 包裹整个字典。
  • 此字典将国家(值)与城市(键)关联起来。

要更改与键关联的值,请使用相同的语法。让我们将 Madrid 的值设置为如下所示

  • 代码中正在使用内置的 Python 方法 dict_items 来创建字典。
  • 此函数的参数是一个元组列表,每个元组代表一个键值对。
  • 值是元组中的第二个成员,而键是第一个。
  • 在此实例中,France、Italy 和 United Kingdom 是适当的值,键是“Paris”、“Rome”和“Madrid”。
  • 在最终字典中,每个城市(键)都将映射到其国家(值)。

现在让我们删除字典中的其中一对。

  • 代码片段调用 dictionary_capitals Python 字典的 keys() 函数。
  • keys() 函数返回一个视图对象,显示字典中所有键的列表。
  • capital_countries 变量的内容在 Python 代码的一行中打印。
  • 内置的 Python 方法 print() 用于将数据输出到控制台。
  • 预计 capital_countries 将是一个字典,这是一种预构建的 Python 数据类型,用于保存键值对。
  • 当运行此行代码时,整个字典 capital_countries 将被写入控制台。

输出

 
{'Paris': 'France', 'Rome': 'Italy', 'Madrid': 'United Kingdom'}   

您也可以使用 .clear() 函数来删除字典中的每个键值对

字典循环

如果要在 Python 中获取所有键值对的可迭代列表,请使用 .items() 函数

  • 此代码正在调用名为 capital_countries 的 Python 字典对象的 values() 函数。
  • values() 函数返回一个视图对象,其中包含字典中每个项目的列表。
  • 在此实例中,将返回 capital_countries 字典中保存的所有首都城市(值)。

输出

 
The capital of France is Paris
The capital of Italy is Rome
The capital of United Kingdom is Madrid   

同样,您可以使用 .keys() 和 .values() 方法分别获取包含键和值的可迭代列表

  • 为了构建类似于字典的对象,代码使用了 Python collections 包中的 Counter 类。
  • 要计数的事物作为键存储在为每个 Counter 对象初始化的字典中。
  • 字典的值表示每个事物的数量。
  • 初始 Counter 对象计算“aaa”三次,“ccc”两次,“bbb”一次。
  • 第二个 Counter 对象计算“Red”四次,“blue”两次。
  • 第三个 Counter 项中,“Dogs”和“Cats”各计算八次。
  • 您可以使用这些 Counter 对象计算集合中事物的频率。

输出

 
PARIS
ROME
MADRID   

哈希映射在现实世界中的应用

在数字时代,哈希映射是非常有用的数据结构,几乎无处不在。以下是哈希映射的一些实际用途:

  • 数据库索引。大量数据经常使用哈希映射进行索引和搜索。许多网络浏览器都使用哈希映射来存储索引网页。
  • 缓存管理。现代操作系统使用哈希映射来组织缓存内存,以便可以快速访问频繁使用的数据。
  • 密码学。哈希映射对密码学研究至关重要。加密算法利用哈希映射通过网络提供安全交易并确保数据完整性和有效性。
  • 区块链。区块链的基本单元是哈希映射。每次网络上发生交易时,哈希函数都会接收交易数据作为输入并输出唯一结果。区块链上的每个区块都携带着前一个区块的哈希值,从而创建了一个区块链。

哈希映射的最佳实践和常见错误

哈希映射是非常有效和适应性强的数据结构。然而,它们也有缺点和限制。为了处理哈希映射的典型问题,记住一些事情和最佳实践至关重要。

键不得更改

这很合理:如果键的内容发生变化,Python 将无法确定与键关联的值,因为哈希函数将产生不同的哈希值。

处理哈希映射冲突

只有当哈希表中的每个项目都对应一个不同的位置时,哈希才起作用。然而,哈希函数有时会为不同的输入提供相同的结果。例如,当使用除法哈希函数时,不同的数字可能会有相同的哈希函数(即,当应用模除时产生相同的余数),这会导致冲突问题。必须避免事故,并且有许多可用方法。幸运的是,Python 在字典方面会内部处理此类冲突。

了解负载因子

负载因子是表中项目数与桶总数之比。它用作衡量数据估计分布程度的指标。一般来说,数据分布均匀性越高,发生冲突的可能性越小。再次强调,对于字典,Python 会在添加或删除新键值组合时自动调整表大小。

识别您的性能

一个好的哈希函数会将条目均匀地分布在哈希表中,减少冲突次数,并且易于计算。这可以通过使哈希函数更复杂或扩大表大小来实现。虽然这对于少量项目效果很好,但对于大量潜在项目来说是不切实际的,因为它会导致哈希映射效率低下并需要大量内存。

您需要字典吗?

尽管字典很棒,但您的特定数据和需求可能更适合替代数据结构。最终,在某些情况下,字典的通用性较差,处理起来也更具挑战性,因为它们不支持索引、切片和连接等标准操作。

Python 中哈希映射的其他实现

如前所述,Python 使用内置字典来实现哈希映射。需要记住的是,哈希映射可以与其他第三方库和原生 Python 特性一起使用。

让我们看几个更著名的例子。

Defaultdict

每次您尝试访问字典中不存在的键时,Python 都会生成 KeyError。使用 .get() 函数搜索信息是避免此问题的一种方法。然而,使用 Defaultdict(存在于 collections 模块中)是一种有效的方法。字典和 defaultdict 几乎相同。唯一的区别是 defaultdict 为不存在的键提供默认值,它从不生成错误。

在此程序中,capitals 对象是一个默认字典,它是 collections 库中的一种数据结构,当传入不存在的键时,它将返回一个默认值,而不是引发 Joe capital not found 异常。Paris 到 France,Berlin 到 Germany,这两个键值对都添加到字典中。在这里,对字典中不存在的键 ('Ankara') 的访问尝试返回默认值,而不是 KeyError。

输出

 
France
Germany
capital not found   

Counter

Python 字典的 Counter 子类是专门为计数可哈希项目而创建的。元素作为键保存在此字典中,而它们的计数作为值保存。

Counter 可以通过几种方式初始化

  • 通过一系列项目。
  • 通过字典的键和计数。
  • 将名称链接到值。

说明

该程序展示了如何使用 Python collections 模块中的多种方法创建 Counter 对象。可迭代对象的计数器是专用字典,用于统计特定项目的出现次数。此代码计算字符串“aaabbbcccaaa”中的字符以构建 c1,它是每个字符的计数的总和。使用关键字参数,c2 立即初始化并计算颜色名称(红色和蓝色)的出现次数。一个计算各种动物(猫和狗)的词汇表用于创建 c3。当计数器按顺序打印时,它们会显示其相应的元素和计数作为 Counter 对象。

输出

 
Counter({'a': 6, 'b': 3, 'c': 3})
Counter({'red': 4, 'blue': 2})
Counter({'dogs': 8, 'cats': 4})   

Counter 类包含几种方便的方法来执行典型的计算。

说明

以下代码展示了获取和显示来自 Python collections 模块的名为 c3 的 Counter 对象的属性和方法的不同方法。打印 c3 的键(Counter 中的唯一项)后,打印值(每个元素的计数)。它使用 c3.elements() 将每个元素显示为列表,包括根据其 Counter 计数重复的元素。sum(c3.values()) 函数用于获取所有项的总计数。最后,使用 most_common(2) 技术显示前两个最常见的组件及其计数。可以借助此代码检查 Counter 元素的频率分布。

输出

 
Keys of the counter: dict_keys(['cats', 'dogs'])
Values of the counter: dict_values([4, 8])
All elements as a list: ['cats', 'cats', 'cats', 'cats', 'dogs', 'dogs', 'dogs', 'dogs', 'dogs', 'dogs', 'dogs', 'dogs']
Total count of all elements: 12
Top 2 most common items: [('dogs', 8), ('cats', 4)]   

使用 Scikit-learn 的哈希方法

Sklearn,另一个名称是 Scikit-learn,是一个功能强大、开源的 Python 机器学习包。它旨在简化在 Python 中使用统计和机器学习模型的过程。

Sklearn 包含许多哈希技术,这对于特征工程过程非常有帮助。

CountVectorizer 技术是最常用的技术之一。它用于根据文本中出现的每个单词的频率将文本转换为向量。CountVectorized 在执行文本分析时特别有用。

说明

该软件使用 sklearn.feature_extraction.text 模块中的 CountVectorizer 从一组示例文本文档创建词频的数值表示。在对文本进行标记并计算每个不同单词的实例后,CountVectorizer 将数据以稀疏矩阵格式保存。打印的唯一单词列表(词汇表)表示在计数时考虑了哪些单词。然后,通过将稀疏矩阵转换为 pandas DataFrame,直观地表示每个单词在文档中的频率,其中每行代表一个文档,每列代表词汇表中的一个不同单词,显示每个单词在每个文档中出现的频率。

输出

 
Unique words: ['analyst' 'career' 'course' 'data' 'Javatpoint' 'new' 'python' 'skill'
 'this' 'to' 'track' 'welcome']
   analyst  career  course  data  Javatpoint  new  python  skill  this  to  \
0        0       0                1        0           1                  1        1         0       1     1   
1        0       0                 0         0         1                   1       0         1       1    1   
2        1       1                 0         1         1                   1       0          0     1     1   

   track  welcome  
0      0        1  
1      1        1  
2      1        1     

sklearn 中的其他哈希技术包括 DictVectorizer 和 FeatureHasher。您可以通过注册我们的 Python 课程《使用机器学习进行学校预算编制》来了解它们在实际场景中的工作原理。