2017-08-08 4 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は文字の序数に直接結びついており、セットはハッシュマップに基づいているからです。あなたはハッシュ衝突を取得を開始するために十分な文字を導入した場合でも、見かけの順序は完全に一緒に保持されていません。

; 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)は、Javaがそのハッシュコードを定義する方法であるため、1を返します。しかし、Clojure's hash functionは、murmur3を使用しています。これは数字を入力するだけの数値とはかなり異なる値を返します。は1392991556です。私はこれに関する専門家ではありませんが、Javaの組み込みハッシュ関数の代わりにmurmurを使用する主な動機は避けていますセキュリティ上の理由からハッシュ衝突。タイミング攻撃か何か?

+0

興味深い!だから、文字はJavaのハッシュ実装を使用し、数字はClojureを使用しますか? – Carcigenicate

+0

はい、[hasheq'](https://github.com/clojure/clojure/blob/6dcb5e2/src/jvm/clojure/lang/Util.java#L164)には文字のオーバーライドがありません。 – amalloy

+0

クール。詳細な分析をいただきありがとうございます。 – Carcigenicate

関連する問題