Permalink
Showing with 49 additions and 4 deletions.
  1. +10 −0 src/clj/clojure/core.clj
  2. +4 −4 src/jvm/clojure/lang/Murmur3.java
  3. +35 −0 test/clojure/test_clojure/data_structures.clj
@@ -4694,6 +4694,16 @@
:static true}
[x] (. clojure.lang.Util (hasheq x)))
+(defn mix-collection-hash
+ "Mix final collection hash for ordered or unordered collections.
+ hash-basis is the combined collection hash, count is the number
+ of elements included in the basis. Note this is the hash code
+ consistent with =, different from .hashCode.
+ See http://clojure.org/data_structures#hash for full algorithms."
+ {:added "1.6"
+ :static true}
+ [^long hash-basis count] (clojure.lang.Murmur3/mixCollHash hash-basis count))
+
(defn interpose
"Returns a lazy seq of the elements of coll separated by sep"
{:added "1.0"
@@ -91,7 +91,7 @@ public static int hashUnencodedChars(CharSequence input){
return fmix(h1, 2 * input.length());
}
-public static int fixCollHash(int hash, int count){
+public static int mixCollHash(int hash, int count){
int h1 = seed;
int k1 = mixK1(hash);
h1 = mixH1(h1, k1);
@@ -108,7 +108,7 @@ public static int hashOrdered(Iterable xs){
++n;
}
- return fixCollHash(hash, n);
+ return mixCollHash(hash, n);
}
public static int hashUnordered(Iterable xs){
@@ -120,7 +120,7 @@ public static int hashUnordered(Iterable xs){
++n;
}
- return fixCollHash(hash, n);
+ return mixCollHash(hash, n);
}
private static int mixK1(int k1){
@@ -148,4 +148,4 @@ private static int fmix(int h1, int length){
return h1;
}
-}
+}
@@ -1074,3 +1074,38 @@
"Banana" "like", "apple" "love", "7th" "indifferent") ]]
(doseq [m1 maps1, m2 maps1]
(is-same-collection m1 m2))))
+
+;; *** Collection hashes ***
+;; See: http://clojure.org/data_structures#hash
+
+(defn hash-ordered [collection]
+ (-> (reduce (fn [acc e] (unchecked-add-int (unchecked-multiply-int 31 acc) (hash e)))
+ 1
+ collection)
+ (mix-collection-hash (count collection))))
+
+(defn hash-unordered [collection]
+ (-> (reduce unchecked-add-int 0 (map hash collection))
+ (mix-collection-hash (count collection))))
+
+(defn gen-elements
+ []
+ (gen/vec gen/anything))
+
+(defspec ordered-collection-hashes-match
+ identity
+ [^{:tag clojure.test-clojure.data-structures/gen-elements} elem]
+ (let [v (vec elem)
+ l (apply list elem)]
+ (is (= (hash v)
+ (hash l)
+ (hash (map identity elem))
+ (hash-ordered elem)))))
+
+(defspec unordered-set-hashes-match
+ identity
+ [^{:tag clojure.test-clojure.data-structures/gen-elements} elem]
+ (let [unique-elem (distinct elem)
+ s (into #{} unique-elem)]
+ (is (= (hash s)
+ (hash-unordered unique-elem)))))

0 comments on commit 6aaaa0a

Please sign in to comment.