使用NSUUID周围的包装类作为键来散列问题

时间:2016-04-20 03:06:08

标签: swift dictionary key lldb

** REWRITE **

好的,事实证明我真的在问一个不同的问题。我理解hashValue和==,所以这不相关。

我希望我的包装类BUUID能够“做正确的事”,并且就像NSUUID在字典中的行为一样。

见下文,他们没有。

import Foundation
class BUUID: NSObject {
    init?(str: String) {
        if let uuid = NSUUID(UUIDString: str) {
            _realUUID = uuid
        }
        else {
            return nil
        }
    }

    override init() {
        _realUUID = NSUUID()
    }

    private var _realUUID: NSUUID

    override var description: String { get { return _realUUID.UUIDString } }
    override var hashValue: Int { get { return _realUUID.hashValue } }
    var UUIDString: String { get { print("WARNING Use description or .str instead"); return _realUUID.UUIDString } }
    var str: String { get { return _realUUID.UUIDString } }
}
func ==(lhs: BUUID, rhs: BUUID) -> Bool { return lhs._realUUID == rhs._realUUID }

let a = BUUID()
let b = BUUID(str: a.str)!
print("a: \(a)\nb: \(b)")
print("a === b: \(a === b)")
print("a == b: \(a == b)")

var d = [a: "Hi"]
print("\(d[a]) \(d[b])")


let nA = NSUUID()
let nB = NSUUID(UUIDString: nA.UUIDString)!
print("na: \(nA)\nnB: \(nB)")
print("nA === nB: \(nA === nB)")
print("nA == nB: \(nA == nB)")

var nD = [nA: "Hi"]
print("\(nD[nA]) \(nD[nB])")

结果。请注意,我可以使用NSUUID nB查找并返回nA下的内容。我的BUUID不是这样。

a: 9DE6FE91-D4B5-4A6B-B912-5AAF34DB41C8
b: 9DE6FE91-D4B5-4A6B-B912-5AAF34DB41C8
a === b: false
a == b: true
Optional("Hi") nil

nA: <__NSConcreteUUID 0x7fa193c39500> BB9F9851-93CF-4263-B98A-5015810E4286
nB: <__NSConcreteUUID 0x7fa193c37dd0> BB9F9851-93CF-4263-B98A-5015810E4286
nA === nB: false 
nA == nB: true
Optional("Hi") Optional("Hi")

3 个答案:

答案 0 :(得分:2)

继承自NSObject还假设 isEqual(object:AnyObject?) - &gt; Bool 方法重载:

import Foundation
class BUUID: NSObject {
    init?(str: String) {
        if let uuid = NSUUID(UUIDString: str) {
            _realUUID = uuid
        }
        else {
            return nil
        }
    }

    override init() {
        _realUUID = NSUUID()
    }

    private var _realUUID: NSUUID

    override func isEqual(object: AnyObject?) -> Bool {
        guard let buuid = object as? BUUID else {
            return false
        }

        return buuid._realUUID == _realUUID
    }
    override var description: String { get { return _realUUID.UUIDString } }
    override var hashValue: Int { get { return _realUUID.hashValue } }
    var UUIDString: String { get { print("WARNING Use description or .str instead"); return _realUUID.UUIDString } }
    var str: String { get { return _realUUID.UUIDString } }
}
func ==(lhs: BUUID, rhs: BUUID) -> Bool { return lhs._realUUID == rhs._realUUID }

let a = BUUID()
let b = BUUID(str: a.str)!
print("a: \(a)\nb: \(b)")
print("a === b: \(a === b)")
print("a == b: \(a == b)")

var d = [a: "Hi"]
print("\(d[a]) \(d[b])")


let nA = NSUUID()
let nB = NSUUID(UUIDString: nA.UUIDString)!
print("na: \(nA)\nnB: \(nB)")
print("nA === nB: \(nA === nB)")
print("nA == nB: \(nA == nB)")

var nD = [nA: "Hi"]
print("\(nD[nA]) \(nD[nB])")

答案 1 :(得分:1)

所以答案是使BUUID从NSObject继承,这会覆盖覆盖==的Swiftiness。

所以:

extension BUUID: Hashable {}
class BUUID: CustomStringConvertible {
    // take away all 'override' keywords, nothing to override
    // otherwise same as above
}

有趣!

答案 2 :(得分:0)

此答案与最初提出的问题相关:为什么可以在字典中获得具有相同键值哈希值的两个键值对

此示例说明Dictionary中的键可以具有相同的哈希值,但是对于不同的键,相等操作应该返回false:

func ==(lhs: FooKey, rhs: FooKey) -> Bool {

    return unsafeAddressOf(lhs) == unsafeAddressOf(rhs)
}

class FooKey: Hashable, Equatable {

    var hashValue: Int {

        get {
            return 123
        }
    }
}

var d = Dictionary<FooKey, String>()

let key1 = FooKey()
let key2 = FooKey()

d[key1] = "value1"
d[key2] = "value2"

输出

[FooKey: "value1", FooKey: "value2"]

使用相同哈希的所有密钥肯定不好。在这种情况下,当搜索元素复杂度下降到O(n)(穷举搜索)时,我们遇到了最糟糕的情况。但它会奏效。