☰
DocAgent 仓颉标准库实战:HashMap 的 get/add/contains 函数用法详解
2026/10/14 21:08:34 网站建设 项目流程
  • 人工智能
  • AI 技能
  • 文档
  • 开发工具

【免费下载链接】DocAgent

项目地址:https://gitcode.com/Cangjie-SIG/DocAgent
点击查看免费下载

本篇技术指南以仓颉语言标准库std.collection中的哈希表实现HashMap<K, V>为核心,通过官方示例文件 sample_hashmap_get_add_contains.md 讲解其最基本的三个操作——添加键值对(add)、按键取值(get)与按键判断(contains)。读完本文,你将掌握HashMap的构造方式、Option返回值语义及其安全取值手段,并能直接上手编写可运行的键值对存取代码。

HashMap 是什么

HashMap<K, V>是Map<K, V>接口的哈希表实现,位于仓颉标准库的std.collection包中,定义见 HashMap_class.md。哈希表是一种常用的数据结构,其基本原理是把每个键映射为一个哈希值,再用该哈希值确定元素在底层数组中的存储位置,从而实现快速查找、插入和删除。由于哈希运算与数组下标访问的时间代价基本恒定,哈希表上这三类操作的时间复杂度通常是 O(1)。

需要特别注意的是:因为哈希表底层的数组大小是动态的(插入元素过多时会触发扩容),所以HashMap 不能保证元素的顺序不可变。这与 TreeMap(基于红黑树、按键有序)形成鲜明对比,在 collection_package_overview.md 中有明确说明。此外,std.collection提供的集合类型都不支持并发安全。

HashMap<K, V>的类声明对键类型有约束:K <: Hashable & Equatable<K>,即键必须可哈希且可判等,这是哈希表正确寻址的前提。类本身实现Map<K, V>接口,并扩展了Equatable<HashMap<K, V>>(支持==/!=)与ToString(支持toString())接口。

示例:get/add/contains 的基本用法

仓库中的官方示例 sample_hashmap_get_add_contains.md 完整演示了三个核心函数,代码如下:

import std.collection.* main() { var map: HashMap<String, Int64> = HashMap<String, Int64>() map.add("a", 99) // map : [("a", 99)] map.add("b", 100) // map : [("a", 99), ("b", 100)] var a = map.get("a") var bool = map.contains("a") print("a=${a.getOrThrow()} ") print("bool=${bool.toString()}") return 0 }

运行结果:

a=99 bool=true

这段代码虽短,却覆盖了HashMap最典型的使用流程:先构造空映射,再连续add两个键值对,随后用get取出指定键的值,用contains判断键是否存在。下面逐一拆解每个环节。

构造:HashMap<String, Int64>()

示例通过HashMap<String, Int64>()构造一个键为String、值为Int64的空哈希表。HashMap共提供 5 个构造函数(详见 collection_package_class.md):

构造函数原型说明
默认构造init()默认初始容量为 16
键值对数组init(elements: Array<(K, V)>)根据数组 size 设置容量,重复键按迭代器顺序后者覆盖前者
键值对集合init(elements: Collection<(K, V)>)根据集合 size 设置容量,重复键处理同上
指定容量init(capacity: Int64)容量小于 0 时抛IllegalArgumentException
个数+规则函数init(size: Int64, initElement: (Int64) -> (K, V))由规则函数生成键值对,size 小于 0 时抛IllegalArgumentException

对于元素个数可预估的场景,推荐使用init(capacity)预分配容量,避免插入过程中反复扩容带来的性能开销。

add:将键值对放入 HashMap

public func add(key: K, value: V): Option<V>

add用于把键值对放入HashMap。其关键语义是覆盖策略:对于映射中已有的键,该键对应的值将被新值替换,同时返回旧值;对于新键,则直接添加,返回Option<V>.None。返回值用Option封装,正好让调用方区分"本次是新增还是覆盖"。

示例中两次调用:

map.add("a", 99) // map : [("a", 99)] map.add("b", 100) // map : [("a", 99), ("b", 100)]

执行后映射包含两个键值对。由于Map不允许重复键,每个键最多映射到一个值(见 Map_interface.md),因此若再次map.add("a", 200),"a"的值会被更新为 200,且返回Some(99)。

除单个键值对形式外,add还有一个批量重载add(all!: Collection<(K, V)>): Unit,可按集合迭代器顺序批量放入,同样遵循"已有键被新值替换"的规则,相关完整示例见 sample_hashmap_add_remove_clear.md。

运算符糖:map[key] = value

HashMap对add做了运算符重载:public operator func [](key: K, value!: V): Unit。当键存在时新值覆盖旧值,键不存在时添加键值对。因此map["a"] = 99与map.add("a", 99)效果一致,日常编码中可以按习惯选用。

get:按键取值的正确姿势

public func get(key: K): ?V

get返回指定键映射到的值,返回值类型为Option<V>(语法上写作?V):如果映射中存在该键,返回Some(value);如果不存在,返回Option<V>.None。这一设计避免了"取不存在的键时抛异常或返回空指针"的尴尬,把"可能没有值"这一信息显式地编码进类型系统。

示例中:

var a = map.get("a") print("a=${a.getOrThrow()} ")

map.get("a")得到Option<Int64>,随后调用a.getOrThrow()取出原始Int64值。getOrThrow是Option提供的安全取值方法,定义在 core_package_enums.md:

  • getOrThrow(): T:当实例为Some<T>时返回其中值;若为None则抛出NoneValueException;
  • getOrThrow(exception: () -> Exception): T:当实例为None时,执行传入的异常函数并抛出其返回的异常,适合在键缺失时需要自定义错误信息(如"配置项不存在")的场景。

因此get+getOrThrow的组合适合"键必然存在"的业务假设;如果键可能缺失,更稳妥的做法是先contains判断,或利用Option的match分支分别处理Some与None(HashMap的迭代遍历即采用该模式,参见 sample_hashmap_add_remove_clear.md 中的批量添加示例)。

get同样有运算符重载:public operator func [](key: K): V,即map["a"]直接返回键对应的值。注意该重载在键不存在时会抛NoneValueException(见 collection_package_class.md),所以[]取值的健壮性不如get+ 判空,使用前需自行保证键存在。

contains:判断键是否存在

public func contains(key: K): Bool

contains用于判断映射中是否存在指定键的映射,存在返回true,否则返回false。示例中:

var bool = map.contains("a") print("bool=${bool.toString()}")

因为此前已add("a", 99),所以输出bool=true。contains是典型的"先判断再取"组合的搭档:在键可能缺失的场景下,先contains确认,再安全地取值或走其他逻辑分支。

contains还有一个批量重载contains(all!: Collection<K>): Bool,用于判断是否包含集合中所有键的映射,全部包含才返回true。

一个完整的增查删清演示

为加深对HashMap语义的理解,仓库还提供了配套示例 sample_hashmap_add_remove_clear.md,演示批量添加、删除与清空:

import std.collection.* main() { var map: HashMap<String, Int64> = HashMap<String, Int64>() var arr: Array<(String, Int64)> = [("d", 11), ("e", 12)] map.add("a", 13) print("a=${map.get("a").getOrThrow()} ") map.add(all: arr) // map : [("d", 11), ("e", 12)] var d = map.get("d") print("d=${d.getOrThrow()} ") map.remove("d") // map : [("e", 12)] var bool = map.contains("d") print("bool=${bool.toString()} ") map.clear() // map: [] var bool1 = map.contains("e") print("bool1=${bool1.toString()}") return 0 }

运行结果:

a=13 d=11 bool=false bool1=false

其中remove("d")删除指定键的映射并返回被删值(键不存在时返回None),clear()清空所有键值对。可以看到,删除与清空之后contains的判定随之变为false,三个函数配合即可完成映射的完整生命周期管理。

更多成员函数速览

除add/get/contains外,HashMap还提供一系列常用成员(完整 API 见 HashMap_class.md 与 collection_package_class.md):

函数原型说明
size/capacityprop分别返回键值对个数与容量
addIfAbsent(key: K, value: V): ?V键不存在才添加,否则不做修改并返回旧值
remove(key: K): Option<V>删除指定键的映射,返回被删值或None
removeIf(predicate: (K, V) -> Bool): Unit遍历删除满足条件的键值对,predicate 内修改映射会抛ConcurrentModificationException
replace(key: K, value: V): ?V键已存在则更新值并返回旧值,否则不做修改
reserve(additional: Int64): Unit扩容,剩余容量不足时按容量 1.5 倍规则扩容
keys/values()返回所有键/值的容器视图
iterator()返回HashMapIterator<K, V>用于遍历
entryView(key: K): MapEntryView<K, V>获取指定键的引用视图
clone/toArray/isEmpty()克隆、转数组、判空

小结

HashMap是仓颉标准库std.collection中面向"键值映射 + 快速查找"场景的首选容器:用add(或map[k] = v)写入,用get加getOrThrow(或map[k])读取,用contains判存。其Option化的返回值让缺失键成为可显式处理的常态分支,而非运行时异常。掌握这三个基本函数后,再结合批量add、remove、clear与迭代遍历,即可应对大多数映射类业务需求。相关示例与 API 文档均可从 std/collection 目录下继续查阅。

  • 人工智能
  • AI 技能
  • 文档
  • 开发工具

【免费下载链接】DocAgent

项目地址:https://gitcode.com/Cangjie-SIG/DocAgent
点击查看免费下载

相关推荐

上一篇:如何快速部署 Manga Translator UI Web 服务器:账号、配额与多用户权限完整指南
下一篇:HowToCook 地三鲜完整实战指南:分阶段过油与酱汁挂汁的参数化复刻

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询