2017-08-08 35 views
3

我一直的印象是那台是没有顺序的下,但注意到,人物套做似乎下令:为什么字符集出现需订购?

(seq #{\e \c \b \z \a}) 

=> (\a \b \c \e \z) 

如果我介绍其他类型的字符,就好像他们”

(seq #{\e \A \c \space \b \z \a}) 

=> (\space \A \a \b \c \e \z) 

为什么人物正在根据自己的代码排序,但数字的设置似乎有任意排序:根据字符的代码重新被排序?

回答

10

这是因为Character/hashCode直接连接到人物的序号,并设置基于包含HashMap。但是,如果你介绍的字符足以开始得到哈希冲突,明显的顺序不完全抱在一起:

; the whole alphabet is small enough to avoid collisions 
user=> (apply str (set "abcdefghijklmnopqrstuvwxyz")) 
"abcdefghijklmnopqrstuvwxyz" 
; and observe the hashes are indeed sequential 
user=> (map hash (set "abcdefghijklmnopqrstuvwxyz")) 
(97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122) 

; but go from 26 to 36 elements, and you start to see collisions 
user=> (apply str (set "abcdefghijklmnopqrstuvwxyz")) 
"abcdefghijklmno0p1q2r3s4t5u6v7w8x9yz" 
user=> (map hash (set "abcdefghijklmnopqrstuvwxyz")) 
(97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 48 112 49 113 50 114 51 115 52 116 53 117 54 118 55 119 56 120 57 121 122) 

但你也知道,当然,这不是一个定义的行为,但执行是如何发生目前工作。

现在,你问为什么不这样做的数字:原因是,Clojure中明确地避免了它! (.hashCode 1)返回1,因为这是Java的如何定义它的哈希码。但Clojure's hash function使用murmur3,这对于数字返回完全不同的价值不仅仅是返回输入:(hash 1)产生1392991556.我不是这方面的专家,但我相信的主要动机使用,而不是Java的内置散列函数避免杂音哈希碰撞出于安全原因。定时攻击什么的?

+0

有趣!所以字符使用Java的哈希实现,而数字使用Clojure的? – Carcigenicate

+0

是的,有简单地在用于字符没有重写['hasheq'](https://github.com/clojure/clojure/blob/6dcb5e2/src/jvm/clojure/lang/Util.java#L164)。 – amalloy

+0

很酷。感谢您的深入分析。 – Carcigenicate