You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift Set插入同ID对象未替换旧值,是特性还是用法有误?

Swift Set插入相同标识元素时不替换的原因及解决方法

这是Swift Set的既定工作机制,并非你的用法错误。

核心原因

Swift的Set依赖Hashable协议实现元素唯一性,判定逻辑为:

  1. 两个元素的哈希值相等(通过hash(into:)计算)
  2. 两个元素通过==运算符判定为相等

当向Set插入元素时,若集合中已存在相等的元素,insert方法会直接忽略新元素——因为Set认为这两个元素是同一个对象,无需替换。

结合你的代码来看:你为Object自定义的Equatable和Hashable实现仅以id作为判定依据,这意味着只要id相同,两个Object就会被Set视为同一元素。因此插入obj2时,Set检测到已有相等的obj1,自然不会替换旧元素。

解决方法

根据业务需求,可选择以下两种处理方式:

1. 保留id作为唯一标识,需要更新其他属性

若你需要用id区分唯一对象,且希望新元素覆盖旧元素,可以先移除旧元素再插入新元素:

var collection = Set<Object>()
let obj1 = Object(id: "1", action: .delete, code: 1)
collection.insert(obj1)
let obj2 = Object(id: "1", action: .update, code: 4)

// 利用相等性判定移除旧元素
collection.remove(obj2)
collection.insert(obj2)

print(collection.first!.description) // 输出:`update` on `1` with #4

更简洁的方案是使用字典,以id为键存储对象,字典赋值时会自动覆盖相同键的值:

var collectionDict = [String: Object]()
let obj1 = Object(id: "1", action: .delete, code: 1)
collectionDict[obj1.id] = obj1
let obj2 = Object(id: "1", action: .update, code: 4)
collectionDict[obj2.id] = obj2

print(collectionDict["1"]!.description) // 输出:`update` on `1` with #4

2. 将其他属性纳入唯一性判定

若不同action或code的Object应被视为不同元素,需修正Equatable和Hashable实现,把所有相关属性纳入判断:

struct Object: Equatable, Hashable {
    let id: String
    let action: Action
    let code: UInt8
    var description: String {
        return "`\(self.action)` on `\(self.id)` with #\(self.code)"
    }
    init(id: String, action: Action, code: UInt8) {
        self.id = id
        self.action = action
        self.code = code
    }
    func hash(into hasher: inout Hasher) {   
        hasher.combine(self.id)
        hasher.combine(self.action)
        hasher.combine(self.code)
    }
    static func == (lhs: Object, rhs: Object) -> Bool {   
        return lhs.id == rhs.id && lhs.action == rhs.action && lhs.code == rhs.code
    }
}

修改后,obj1和obj2会被视为不同元素,插入后Set中会同时存在两个对象(需确保业务逻辑允许)。

内容的提问来源于stack exchange,提问作者Youmate

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 22:53:11