For some applications, it could be desirable to compute java.util.List hashCode()s backwards, recursively from back to front, rather than front-to-back as defined in the API [1]. For instance, in Clojure this would enable computing the hash values for all of the rests of a seq for free while computing its hash value. This requires just a tiny bit of math and understanding of modular arithmetic. Clojure code showing how this can be done follows.
[1] http://java.sun.com/j2se/1.4.2/docs/api/java/util/List.html#hashCode()
(defn forward-hash "How hashCode() is defined in java.util.List" [s] (loop [s (seq s) h (int 1)] (if s (recur (rest s) (int (unchecked-add (unchecked-multiply h 31) (hash (first s))))) h))) (def int-pow (memoize (fn [x n] (let [x (int x) n (int n)] (cond (zero? n) 1 (even? n) (let [h (int-pow x (/ n 2))] (unchecked-multiply h h)) :else (unchecked-multiply x (int-pow x (dec n)))))))) (defn backward-hash "Compute the same value as forward-hash, but back-to-front." [s] (let [s (seq s) p (int-pow 31 (count (rest s)))] (if s (unchecked-add (unchecked-multiply 30 p) (unchecked-add (int (backward-hash (rest s))) (unchecked-multiply (int (hash (first s))) p))) 1))) user> (map #(% (vec (range 1000))) [forward-hash backward-hash #(.hashCode %)]) (133786869 133786869 133786869) |
Update: I posted this on the Clojure issue page here. Note a small caveat there: it is not allowed by Java that (.equals [] (seq [])), so Clojure collections and seqs cannot be comparable in general. However, everything carries through for non-empty seqs and collections.
Juana
May befor (var i = 0; i < this.length; i++) {notfor (i = 0; i < this.length; i++) {And I think if we cash this.length it was more faster, fllaniy:String.prototype.hashCode = function(){ var hash = 0, len = this.length; if ( len === 0 ) return hash; for( var i = 0; i < len; ++i ) { char = this.charCodeAt(i); hash = ((hash<<5)-hash)+char; hash = hash & hash; // Convert to 32bit integer } return hash;}