尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

一文搞懂Set集合:从原理到多语言实战与常见报错排查

发布时间:2026/9/3 5:41:39

资讯中心
01
ARTICLE

一文搞懂Set集合:从原理到多语言实战与常见报错排查

一文搞懂Set集合:从原理到多语言实战与常见报错排查
在日常开发中我们经常在代码里看到set这个词。刚开始接触时我一度以为它只是“设置”的意思比如git config --set、setTimeout、setContentView后来才发现它还有一个非常重要的身份——集合Set。很多新手在刷 LeetCode、写业务代码时会遇到“用 Set 去重”“求两个数组的交集”这类需求但往往对 Set 的原理、适用场景和不同语言实现方式一知半解。本文就围绕“set 分享”这个主题系统地梳理一下集合的前世今生、多语言使用方式、典型应用场景以及高频报错排查方案帮助大家在实际开发中把 Set 用对、用好。1. set 是什么它到底解决了什么问题1.1 从单词“set”说起set在英文中有“放置、设置、集合”等含义。在编程领域它主要承担两种完全不同的角色动词设置某个值、配置某个选项。例如setTimeout设置定时器UPDATE users SET age 18表示把 age 字段设置为 18git config --global user.name等。名词集合Set一种数据结构表示“不包含重复元素”的一组数据的容器。本文的核心是名词意义上的集合但也会在数据库和环境配置章节中介绍动词意义上的SET因为这两者经常在同一个项目里出现很多初学者容易混淆。1.2 集合Set的专业定义在计算机科学中Set集合是一种抽象数据类型它存储一组互不相同的元素。和数组Array、列表List相比Set 最核心的特征是元素唯一性同一个 Set 中不会出现两个相等的元素。无序性大多数 Set 实现不保证元素的插入顺序部分实现如 Java 的 LinkedHashSet 除外。高效的查找、插入、删除基于哈希表实现的 Set平均时间复杂度为 O(1)。简单来说如果你需要一个“装着不重复数据”的容器并且经常需要判断“某个元素是否存在”Set 通常是最合适的选择。1.3 常见应用场景数据去重从一份原始数据中快速去除重复项。快速判重判断某个值是否已经出现过例如爬虫去重、题库判重。集合运算求两个集合的交集、并集、差集常用于标签系统、权限系统。缓存Key 管理记录一批需要批量处理的 Key。防止重复提交把已提交的请求 ID 放入 Set重复请求直接拒绝。1.4 为什么开发者需要掌握 Set我见过不少开发者处理“去重”时喜欢用两层 for 循环或者用列表contains()方法逐个判断。在小数据量下没有问题一旦数据量上升到万级、十万级性能会急剧下降。掌握 Set 之后你可以用更简洁、更高效的代码完成同样的事情同时还能利用现成的集合运算方法减少自己造轮子的概率。2. 环境准备与语言差异说明2.1 本文涉及的语言与环境由于Set是各大编程语言通用的数据结构本文会结合 Python、Java、C、JavaScript 四种常见语言进行对比演示。你不需要把这四种语言全部装好只需要安装你日常工作中最常用的一门即可。语言推荐版本用途Python3.8数据分析、脚本、后端开发JavaJDK 8企业级后端开发CC11 及以上算法竞赛、性能敏感场景JavaScript / TypeScriptNode.js 14 或现代浏览器前端开发、Node 后端版本需要根据你的项目实际情况调整本文示例以常见环境为例重点演示配置思路。代码本身大多兼容旧版本只有个别新特性会额外说明。2.2 为什么把多种语言放在一起讲很多初学者学 Set 时只看了一门语言比如只学了 Python 的set工作后换到 Java 却发现Set是一个接口不能直接实例化容易产生困惑。把多语言写法放在一起对比可以帮你建立“数据结构是思想语言只是语法外壳”的认知。后续面试、跳槽、阅读开源代码时也能更快地切换上下文。3. 集合的核心概念与原理拆解3.1 集合的基本特征唯一性、无序性、可变性先看一个 Python 的最小示例# Python 中创建一个集合 fruits {apple, banana, apple, orange} print(fruits)输出结果{banana, apple, orange}你会发现连续写了两个apple但输出只有一个。这说明集合自动完成了去重。再注意一点输出顺序可能和你写入的顺序不一致这正是“无序性”的体现。这里需要进一步说明的是Python 的底层实现是哈希表元素的存储位置由哈希值决定所以顺序并不是人为可控的。在 Java 中Set是一个接口常用实现类有HashSet、LinkedHashSet、TreeSetimport java.util.HashSet; import java.util.Set; public class SetDemo { public static void main(String[] args) { SetString fruits new HashSet(); fruits.add(apple); fruits.add(banana); fruits.add(apple); fruits.add(orange); System.out.println(fruits); } }输出同样是去重后的结果[banana, orange, apple]Java 的HashSet底层是HashMapLinkedHashSet在哈希表基础上额外维护了一个双向链表因此能够保证插入顺序TreeSet底层是红黑树元素会按照自然顺序或比较器排序。3.2 Set 与其他数据结构的区别很多初学者分不清 Set 和 List、Map 的区别。用一个表格来对比特性Set集合List列表Map映射元素是否重复不允许重复允许重复Key 不允许重复Value 可以重复是否有序大部分无序部分实现有序有序按插入顺序大部分无序存储内容单个元素单个元素键值对典型实现HashSet、TreeSetArrayList、LinkedListHashMap、TreeMap查找效率O(1) 或 O(log n)O(n)O(1) 或 O(log n)从使用角度来看可以简单记忆为你想存一组不重复的值用 Set。你想按顺序存一组值不关心是否重复用 List。你想通过一个 Key 快速找到对应的 Value用 Map。3.3 集合的哈希原理为了更好地使用 Set必须理解它背后的哈希原理。当往一个基于哈希表的 Set 中添加元素时大致流程如下调用元素的hashCode()方法Python 中是__hash__C 中是std::hash得到哈希值。根据哈希值计算元素在底层数组中的存储位置。如果该位置没有元素直接放入。如果该位置已经有元素调用equals()方法判断两个元素是否相等。如果相等认为元素重复不插入如果不相等用链表或红黑树解决冲突。这也是为什么自定义对象放入 Set 时通常需要同时重写equals()和hashCode()否则可能无法正确去重。后面完整案例中会演示这个问题。3.4 什么是 set abstraction在算法和数学视角下set abstraction 常被翻译为“集合抽象”。它指的是把“一组不同对象的整体”抽象为一个集合对象并提供标准的集合操作成员判断、并集、交集、差集等。理解这个抽象有助于在不同语言之间迁移你的知识。4. 不同语言中的 Set 实战对比4.1 Python内置 set 与 frozensetPython 中使用 set 非常直观除了基本的创建和添加它提供了丰富的集合运算。# 创建集合的两种方式 set1 {1, 2, 3} set2 set([3, 4, 5]) # 用列表转集合 # 添加与删除 set1.add(4) # 添加元素 set1.discard(10) # 删除元素不存在也不报错 set1.remove(2) # 删除元素不存在会抛 KeyError # 集合运算 a {1, 2, 3, 4} b {3, 4, 5, 6} print(交集:, a b) # {3, 4} print(并集:, a | b) # {1, 2, 3, 4, 5, 6} print(差集:, a - b) # {1, 2} print(对称差集:, a ^ b) # {1, 2, 5, 6} print(是否子集:, {1, 2}.issubset(a)) # True如果需要一个不可变的集合可以使用frozenset它可以用作字典的 Key也可以放进另一个集合中fs frozenset([1, 2, 3]) # fs.add(4) # 这会报错AttributeError4.2 JavaHashSet、LinkedHashSet、TreeSet 的选择Java 中 Set 的 API 方法名更长但语义清晰import java.util.*; public class SetCompareDemo { public static void main(String[] args) { SetInteger hashSet new HashSet(); hashSet.add(3); hashSet.add(1); hashSet.add(2); hashSet.add(3); System.out.println(HashSet: hashSet); SetInteger linkedHashSet new LinkedHashSet(); linkedHashSet.add(3); linkedHashSet.add(1); linkedHashSet.add(2); linkedHashSet.add(3); System.out.println(LinkedHashSet: linkedHashSet); SetInteger treeSet new TreeSet(); treeSet.add(3); treeSet.add(1); treeSet.add(2); treeSet.add(3); System.out.println(TreeSet: treeSet); } }运行结果HashSet: [1, 2, 3] LinkedHashSet: [3, 1, 2] TreeSet: [1, 2, 3]三个实现类的选择策略如下只是去重不关心顺序用HashSet。需要去重且保持插入顺序用LinkedHashSet。需要去重且元素自动排序用TreeSet但它要求元素实现Comparable接口或者传入比较器。4.3 Cstd::set 与 std::unordered_setC 中std::set底层是红黑树元素自动排序查找复杂度 O(log n)。std::unordered_set底层是哈希表元素不排序查找复杂度平均 O(1)。#include iostream #include set #include unordered_set int main() { // 有序集合 std::setint orderedSet; orderedSet.insert(3); orderedSet.insert(1); orderedSet.insert(2); orderedSet.insert(3); // 重复元素不会插入 std::cout std::set: ; for (int v : orderedSet) { std::cout v ; } std::cout std::endl; // 无序集合 std::unordered_setint unorderedSet; unorderedSet.insert(3); unorderedSet.insert(1); unorderedSet.insert(2); unorderedSet.insert(3); std::cout std::unordered_set: ; for (int v : unorderedSet) { std::cout v ; } std::cout std::endl; // 查找 if (unorderedSet.find(2) ! unorderedSet.end()) { std::cout 找到元素 2 std::endl; } return 0; }注意std::set输出结果是1 2 3而std::unordered_set的输出顺序不确定。在算法竞赛和性能敏感场景中如果不需要排序优先使用unordered_set。4.4 JavaScriptSet 与数组相互转换JavaScript 中的Set从 ES6 开始提供用法也很简单// 创建 Set const set new Set(); set.add(1); set.add(2); set.add(2); // 重复值被忽略 set.add(hello); console.log(set); // Set(3) { 1, 2, hello } // 判断是否存在 console.log(set.has(2)); // true // 删除 set.delete(1); console.log(set.size); // 2 // 遍历 set.forEach(value { console.log(value); }); // 与数组互相转换 const arr [1, 2, 2, 3, 4, 4]; const uniqueArr [...new Set(arr)]; console.log(uniqueArr); // [1, 2, 3, 4]这里最常用的场景就是数组去重。使用[...new Set(arr)]或Array.from(new Set(arr))一行代码搞定比手写遍历简洁得多。4.5 多语言对比小结不管是什么语言Set 的核心操作都可以归纳为添加、删除、查找、遍历、求并集/交集/差集。下面是不同语言中对应操作的速查表操作PythonJavaCJavaScript添加s.add(x)set.add(x)s.insert(x)set.add(x)删除s.remove(x)set.remove(x)s.erase(x)set.delete(x)判断存在x in sset.contains(x)s.find(x) ! s.end()set.has(x)长度len(s)set.size()s.size()set.size交集a ba.retainAll(b)遍历判断或使用算法手动遍历并集aba.addAll(b)手动插入5. 完整实战案例基于 Set 的用户标签系统5.1 需求分析假设你正在开发一个用户标签系统。运营人员会给用户打上多个标签比如“老用户”“会员”“促销敏感”“高消费”。你需要实现以下几个功能给一个用户添加一批标签并且自动去重。计算两个不同用户有哪些共同标签交集。给某个用户批量增加另一批标签。统计一个用户拥有多少标签。这是一个非常典型的使用 Set 的业务场景。如果用 List 实现判断“共同标签”时需要两层循环代码又长又容易出错。用 Set 则可以直接调用现成方法。5.2 项目结构与初始化为了简化演示这里不引入数据库直接用 Python 写一个脚本模拟内存中的标签系统。项目结构如下user_tag_system/ ├── tag_system.py └── main.py5.3 编写核心代码先写一个简单的用户标签管理类# 文件路径user_tag_system/tag_system.py class UserTagSystem: 用户标签系统基于 set 实现自动去重和集合运算。 def __init__(self): # 每个用户对应一个 set self.user_tags {} def add_tags(self, user_id, tags): 给用户添加标签。 :param user_id: 用户 ID :param tags: 标签列表或集合 if user_id not in self.user_tags: self.user_tags[user_id] set() self.user_tags[user_id].update(tags) def remove_tag(self, user_id, tag): 移除用户的某个标签。 if user_id in self.user_tags: self.user_tags[user_id].discard(tag) def get_tags(self, user_id): 获取用户的全部标签。 return self.user_tags.get(user_id, set()) def get_common_tags(self, user_id1, user_id2): 获取两个用户的共同标签。 tags1 self.get_tags(user_id1) tags2 self.get_tags(user_id2) return tags1 tags2 def count_tags(self, user_id): 统计用户标签数量。 return len(self.get_tags(user_id)) if __name__ __main__: system UserTagSystem() # 用户 1001 添加标签 system.add_tags(1001, [老用户, 会员, 高消费]) # 重复添加观察去重效果 system.add_tags(1001, [会员, 促销敏感]) # 用户 1002 添加标签 system.add_tags(1002, [新用户, 促销敏感, 高消费]) print(用户 1001 标签:, system.get_tags(1001)) print(用户 1002 标签:, system.get_tags(1002)) print(共同标签:, system.get_common_tags(1001, 1002)) print(用户 1001 标签数量:, system.count_tags(1001))5.4 运行与验证在项目目录下执行cd user_tag_system python tag_system.py预期输出用户 1001 标签: {促销敏感, 高消费, 老用户, 会员} 用户 1002 标签: {高消费, 促销敏感, 新用户} 共同标签: {高消费, 促销敏感} 用户 1001 标签数量: 4可以看到尽管用户 1001 连续两次添加了“会员”标签最终仍然只有四个标签Set 自动完成了去重。公共标签的计算也只需要一行tags1 tags2非常直观。5.5 扩展处理自定义对象实际项目中标签可能不是一个字符串而是一个完整对象。以 Java 为例如果直接把自定义对象放入HashSet必须重写equals和hashCode否则去重会失效。import java.util.HashSet; import java.util.Objects; import java.util.Set; class Tag { private String code; private String name; public Tag(String code, String name) { this.code code; this.name name; } // 必须重写 equals Override public boolean equals(Object o) { if (this o) return true; if (o null || getClass() ! o.getClass()) return false; Tag tag (Tag) o; return Objects.equals(code, tag.code); } // 必须重写 hashCode Override public int hashCode() { return Objects.hash(code); } Override public String toString() { return Tag{ code code \ , name name \ }; } } public class CustomObjectSetDemo { public static void main(String[] args) { SetTag tagSet new HashSet(); tagSet.add(new Tag(vip, 会员)); tagSet.add(new Tag(vip, 会员)); // code 相同被视为重复 tagSet.add(new Tag(new, 新用户)); System.out.println(tagSet.size()); // 2 System.out.println(tagSet); } }如果不重写hashCode()两个code相同的对象会被分配到不同的哈希桶中HashSet无法识别它们是同一个对象最终 size 会变成 3。这是一个非常隐蔽的坑。6. SQL 中的 UPDATE SET 语句与 Set 相关操作6.1 UPDATE SET 的基本语法除了编程语言中的集合set在数据库中也是一个高频关键字最典型的就是UPDATE语句。它的功能是为已有记录更新字段值。UPDATE users SET age 18, status active WHERE id 1001;其中UPDATE users指定要更新的表。SET age 18, status active指定要修改的字段和新值多个字段用逗号分隔。WHERE id 1001限定要更新的行。6.2 更新语句的常见误区这里必须强调一个关键问题UPDATE 语句一定要带 WHERE 条件。如果你漏写了WHEREUPDATE users SET status inactive;这条语句会把users表中所有行的status都改成inactive。在生产环境执行这种语句后果非常严重。所以在写 INSERT、UPDATE、DELETE 语句时建议先写 WHERE再回头补 SET 字段。执行前先在测试库验证或者用事务包裹起来方便出错后回滚。6.3 使用 EXISTS 子查询配合 UPDATE SET在某些业务场景中需要根据另一张表的数据来更新当前表。例如把已经下过订单的用户标记为“活跃用户”。UPDATE users u SET u.is_active 1 WHERE EXISTS ( SELECT 1 FROM orders o WHERE o.user_id u.id AND o.created_at 2024-01-01 );这里的EXISTS子查询判断用户是否存在符合条件的订单。用这种方式可以避免一次性 JOIN 带来的大数据量临时表开销在更新大数据集时性能通常更稳定。6.4 SQL 中的集合运算符SQL 本身也支持集合运算常见的有UNION、INTERSECT、EXCEPT不同数据库语法略有区别。-- 查询在 A 表中的用户 ID 和在 B 表中的用户 ID 的并集 SELECT user_id FROM table_a UNION SELECT user_id FROM table_b; -- 交集 SELECT user_id FROM table_a INTERSECT SELECT user_id FROM table_b; -- 差集在 A 中但不在 B 中 SELECT user_id FROM table_a EXCEPT SELECT user_id FROM table_b;这些运算和编程语言中的 Set 操作逻辑完全一致理解了集合论SQL 的集合查询也就顺手了。7. set 命令与环境变量配置以 codex 报错为例7.1 开源工具中的 set 参数问题在日常开发中set最常见的另一个场景是环境变量、CLI 参数的配置。近期不少开发者在安装和启动 Codex 相关桌面应用时会遇到一个高频报错ChatGPT failed to start. Unable to locate the Codex CLI binary. Set codex_cli_path or ensure the electron resources include bin/codex.这个报错的字面意思是无法定位 Codex CLI 二进制文件请设置codex_cli_path或者确保 Electron 资源中包含bin/codex。7.2 报错产生的根本原因这类报错通常发生在 Electron 桌面应用启动时。应用内部需要通过 Node.js 子进程调用 Codex CLI但它在启动时找不到可执行文件。常见原因如下未安装 Codex CLI应用默认依赖一个叫做codex的命令行工具但你的机器上没有安装或没有正确加入 PATH。路径配置缺失应用需要读取codex_cli_path这个配置项但你没有配置或者配置的路径错误。应用资源目录不完整有些安装包会把codex可执行文件放在 Electron 的resources/bin/目录中如果安装包不完整文件就不存在。版本不匹配Codex CLI 版本和桌面应用版本不一致导致应用无法识别。7.3 排查步骤与解决思路问题现象常见原因解决思路启动时提示 Unable to locate the Codex CLI binary未安装 Codex CLI确认 CLI 是否安装并检查codex --version提示 set codex_cli_path路径配置为空或错误找到 codex 可执行文件实际位置写入配置resources 目录缺失 bin/codex安装包不完整重新下载完整版本或手动补齐可执行文件安装后发现 version 不兼容版本不一致将 CLI 升级到应用要求的最低版本在命令行中检查 Codex CLI 是否可用的方法codex --version which codex如果which codex有输出说明命令行工具已经安装接下来只需要把它的路径配置到应用的配置文件里。不同应用的配置入口不一样常见做法是在环境变量中添加export codex_cli_path/usr/local/bin/codex在 Windows 环境中可以在 PowerShell 中设置$env:codex_cli_pathC:\Users\你的用户名\AppData\Roaming\npm\codex.cmd设置完成后重启应用再次查看启动状态。这里要注意codex_cli_path配置的是可执行文件的完整路径不是它的上级目录。如果你手动在 Electron 资源目录中补齐bin/codex还需要确保文件有可执行权限。7.4 同类 set 配置问题类似的“set 路径”报错还有很多例如Error: java_home is not set and no java command could be found in your PATHcould not set environment: 150: operation not permitted while system integrity protection is enabledfailed to set session cookie. maybe you are using...这些报错指向同一个本质程序不知道自己依赖的二进制文件或环境变量在哪里。排查思路基本一致先定位依赖是否安装再检查环境变量是否配置最后确认路径是否可以被当前用户访问。在 macOS 上如果遇到operation not permitted这类权限问题通常和系统完整性保护SIP或终端权限有关需要在知道风险的前提下检查系统设置的隐私权限不要随意关闭系统级安全机制。8. 常见问题与排查清单8.1 集合操作常见问题问题现象常见原因解决思路Set 中出现了重复元素自定义对象未重写 hashCode/equals重写这两个方法确保相同对象哈希值一致遍历 Set 时顺序不稳定底层是哈希表本身无序如果需要顺序改用 LinkedHashSet/TreeSetPython 中set无法放入字典Key 或元素必须是不可变对象使用frozenset作为元素大量元素性能下降哈希冲突过多检查 hashCode 设计避免集中冲突JS 中 Set 转数组后顺序变了Set 本身按插入顺序遍历使用Array.from(set)仍保持插入顺序C 中 std::set 遍历慢红黑树访问开销大非排序场景优先使用 unordered_set8.2 环境配置类问题排查清单当遇到和环境变量、二进制路径相关的报错时可以按以下顺序逐步排查先读完整报错信息找到核心关键词例如codex_cli_path、java_home。在命令行中手动执行对应命令确认是否可用。使用whichLinux/macOS或whereWindows查看程序实际路径。检查应用配置文件或环境变量中是否设置了该路径。确认路径是否正确特别注意 Windows 下.cmd和.exe的区别。如果路径正确检查当前用户是否有执行权限。修改配置后必须重启应用或重新加载环境变量。8.3 SQL 更新操作风险预防在数据库场景中UPDATE SET语句最大的风险是误更新全表。下面是一个安全操作模板-- 在事务中执行方便回滚 BEGIN; -- 先查询要更新多少条记录 SELECT COUNT(*) FROM users WHERE status old_status; -- 再执行更新 UPDATE users SET status new_status WHERE status old_status; -- 确认更新结果 SELECT COUNT(*) FROM users WHERE status new_status; -- 确认无误后提交 COMMIT;如果是生产环境建议先备份相关表或者使用工具控制影响行数。任何时候都不要在没有测试和备份的情况下对线上数据库执行批量 UPDATE。9. 最佳实践与工程建议9.1 如何选择合适的数据结构在开始写代码之前先问自己三个问题数据是否允许重复如果允许重复List/Array 可能更合适。是否需要快速判断某个元素是否存在如果需要优先考虑 Set 或 Map。遍历时是否需要保持顺序如果需要选择有序实现。很多问题看起来复杂但一旦确定使用 Set代码会瞬间简化。比如判断两个数组是否有交集用 Python 可以写def has_intersection(list1, list2): return bool(set(list1) set(list2))用 Java 可以写public boolean hasIntersection(ListString list1, ListString list2) { return list1.stream().anyMatch(new HashSet(list2)::contains); }9.2 注意可变性与线程安全在多线程环境中普通的HashSet不是线程安全的。Java 中可以使用ConcurrentHashMap.newKeySet()来创建一个并发安全的 Set。Python 的多线程环境中如果多个线程同时修改同一个 Set建议加锁或者使用threading.RLock。C 中std::set和std::unordered_set也都不支持并发写多个线程同时操作时必须加锁。9.3 集合运算方法的可读性在业务代码中不要为了炫技把集合运算写在一个超长表达式里。比如# 不推荐 result (a | b) - (a b) c # 推荐拆开写并命名 union_ab a | b common_ab a b result (union_ab - common_ab) c代码是写给同事和自己看的清晰比简短更重要。9.4 SQL 安全操作建议每次写 UPDATE 和 DELETE 之前先执行等价的 SELECT确认影响范围。如果可能把数据库账号分为只读账号和写账号业务代码使用最小权限账号。大批量更新数据时分段执行比一次性更新更安全避免长时间锁表。9.5 环境变量与配置管理建议对于 CLI 工具路径、环境变量这类配置建议遵循以下原则把路径配置写入项目的.env文件而不是写死在代码中。在 README 中写清楚启动前需要设置哪些环境变量。在 CI/CD 流水线中提前注入必要的环境变量避免部署后才发现路径错误。配置文件变更后在日志中打印当前使用的配置路径方便定位问题。10. 总结与进一步探索方向本文围绕 set 展开重点讲解了三个层面的内容一是编程语言中的 Set 集合包括它在 Python、Java、C、JavaScript 中的用法和底层原理二是完整实战案例演示了如何使用 Set 构建一个简单的用户标签系统三是 SQL 中的 UPDATE SET 语句以及环境变量中 set 路径配置的常见问题与排查方案说明“set”这个词在软件开发中横跨数据结构、数据库、命令行配置多个领域。如果你刚接触 Set可以优先把 Python 或 JavaScript 中的 Set 练熟它们语法简单能快速上手。接着可以深入学习 Java 中 Set 接口的多个实现类理解哈希值和红黑树的区别。如果你对性能感兴趣可以进一步研究 C 中std::unordered_set的哈希策略以及如何为自定义类型提供高效的哈希函数。对于数据库方向建议重点练习 UPDATE SET 配合 WHERE、EXISTS、事务的使用养成安全操作的习惯。在真实项目中遇到“去重”“判断存在”“求交集”这类需求时可以多想一想 Set 是否能够简化代码。数据结构的选择往往比代码逻辑本身更影响最终的性能和可维护性。希望这篇文章能帮你把 Set 用得更顺手少踩一些看不见的坑。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。