2016-08-30 14 views
0

我偶然發現了我的(相對)舊代碼中的一個錯誤,發現String哈希屬性證明不是密集的唯一:許多不同的字符串具有相同的哈希值。應該使用Swift String哈希索引持久數據?

參考文檔,我只找到「一個無符號整數,可以用作哈希表地址」,它根本沒有任何信息。

我的代碼段很簡單,只要如下:

func getCacheIndex(sUrl: String) -> Int { 
    return sUrl.hash 
} 

,併產生以下,對於給定的不同的字符串(品目參數是不同的,而XXXXXXX表示取代的密鑰串):

FileCache hash is -4052854053573130360 for url 
https://maps.googleapis.com/maps/api/streetview?size=675x900&location=46.414382,10.013988&heading=135&pitch=-0.76&key=XXXXXXXXXXXXXXXXXXX 

FileCache hash is -4052854053573130360 for url 
https://maps.googleapis.com/maps/api/streetview?size=675x900&location=46.414382,10.013988&heading=180&pitch=-0.76&key=XXXXXXXXXXXXXXXXXXX 

String有一個hashValue,但它清楚地表明,我們不應該使用它來堅持之間的任何運行。

你會如何解決這個與斯威夫特?我應該提供自己的哈希碼嗎?

+0

是的,如果你想要穩定的散列和更大的摘要大小,你需要實現你自己的散列函數。類似於SHA2-256將提供一個(驚喜)256位長的散列值。哈希碰撞(即'哈希(a)==哈希(b)其中!= b')是一個不可避免的生活事實。但你想做什麼? –

+0

我正在尋找一個穩定的版本(跨多個運行和iOS版本)來基於URL索引文件。有什麼建議麼? –

回答

0

我暫時用我的應用程序中的自定義func替換原生String.hash。這解決了問題,用更好的表現分佈:

public func hash(_ string: String) -> Int { 
    func djb(_ string: String) -> Int { 

     return string.utf8 
      .map {return $0} 
      .reduce(5381) { 
       ($0 << 5) &+ $0 &+ Int($1) 
     } 
    } 

    return djb(string) 
} 

注:DJB哈希FUNC可以在任何時候進行更換,每當我有時間上的分配工作。