Swift十万级数组过滤性能过慢,求高效优化方案
性能优化方案
1. 正确使用Set进行集合运算(核心优化)
你的第二种实现没用到Set的核心优势——O(1)时间复杂度的contains操作,反而还是在遍历数组做contains,等于白转Set。正确的做法是把两个数组都转为Set,利用集合的内置运算直接求差异:
DispatchQueue.global().async { let beforeSet = Set(beforeStringList) let afterSet = Set(afterStringList) // 已删除元素:仅存在于before数组 let deletedRows = beforeSet.subtracting(afterSet) // 新增元素:仅存在于after数组 let addedRows = afterSet.subtracting(beforeSet) // 批量处理结果,避免在循环里做print这类IO操作 print("已删除条目数:\(deletedRows.count)") print("新增条目数:\(addedRows.count)") }
- 时间复杂度从原来的O(n*m) 降到O(n+m),10万级数据能在毫秒级完成计算。
- Set的哈希查找是Swift内置优化过的,完全能应对这个量级的数据。
2. 在SQLite层面直接计算差异(最优方案)
既然数据来自SQLite表,没必要把全量数据加载到内存再对比,直接让数据库引擎帮你做差异计算——这是数据库的强项,尤其是给字段加索引后,速度会远超内存处理:
查询已删除数据(原表有,新表无)
SELECT value FROM before_table EXCEPT SELECT value FROM after_table;
查询新增数据(新表有,原表无)
SELECT value FROM after_table EXCEPT SELECT value FROM before_table;
或者用LEFT JOIN实现(效果一致):
-- 已删除数据 SELECT b.value FROM before_table b LEFT JOIN after_table a ON b.value = a.value WHERE a.value IS NULL;
- 优势:不需要加载10万条数据到内存,减少IO和内存占用;数据库对这类查询有索引优化,速度更快。
3. 辅助优化细节
- 避免不必要的IO操作:不要在遍历/过滤过程中做
print,先计算完所有差异再批量输出,IO操作会严重拖慢处理速度。 - 提前去重:如果原数组存在大量重复字符串,转Set的过程已经自动去重,能减少后续处理的数据量。
- 内存控制:如果字符串本身极大(比如长文本),可以考虑分批从数据库读取并对比,避免一次性占用过多内存。
内容的提问来源于stack exchange,提问作者ez4nick
相关产品推荐
相关产品推荐

