liveBook · Manning

Hash

As explained in Clojure: The Essential Reference

hash is Clojure's default hashing function, mapping any object, including nil, to a 32-bit signed integer consistent with Clojure hashing rules for supported values.

`hash` is Clojure’s default hashing function. It matters when values—including collections—serve as keys in hash maps: Java’s `hashCode()` alone can perform poorly for some composite keys. section 6.0 section 6.6

`(hash x)` accepts any object, including `nil`, and returns a signed 32-bit `java.lang.Integer`. Numbers, strings, and values implementing `clojure.lang.IHashEq` follow Clojure hashing rules; for other values, `hash` delegates to Java’s `.hashCode()`. section 6.6

A basic result

`(hash "hello")` returns `1715862179`; `(type (hash "hello"))` returns `java.lang.Integer`. Distinct values can still share a hash: the numeric values `-1` and `0`, for example, both have Java `hashCode` value `0` in the illustrated comparison, but different Clojure `hash` results. section 6.6

The related helpers address collection hashing directly. `hash-ordered-coll` accounts for element order; `hash-unordered-coll` does not. Both require a `java.lang.Iterable`: passing `nil` raises `NullPointerException`, while a non-iterable value raises `ClassCastException`. `mix-collection-hash` takes a hash basis and a count when integrating collection hashes. section 6.6

(=
  (hash-unordered-coll [1 2 3]) ; #1
  (hash-unordered-coll [3 2 1])
  (hash-unordered-coll #{1 2 3}))
;; true

(=
  (hash-ordered-coll [1 2 3]) ; #2
  (hash-ordered-coll [3 2 1])
  (hash-ordered-coll #{1 2 3}))
;; false

Compare the same elements in different orders: their unordered collection hashes agree, while their ordered collection hashes do not. section 6.6

Equality and hashing need attention at Java interop boundaries. A Java `ArrayList` and a Clojure vector can compare equal yet produce different results from `hash`; a Java `HashMap` also cannot be passed directly to `hash-unordered-coll` because it is not `Iterable`. For that map case, hashing its entries and mixing in their count produces the illustrated Clojure-map hash. section 6.6

(defn hash-java-map [^java.util.Map m]
  (let [iter (.. m entrySet iterator)] ; #1
    (loop [ret 0 cnt 0]
      (if (.hasNext iter)
        (let [^java.util.Map$Entry item (.next iter) ; #2
              kv [(.getKey item) (.getValue item)]]
          (recur
            (unchecked-add ret ^int (hash kv)) ; #3
            (unchecked-inc cnt)))
        (.intValue ^Long (mix-collection-hash ret cnt)))))) ; #4

(= (hash (HashMap. {1 2 3 4})) ; #5
   (hash {1 2 3 4}))
;; false

(= (hash-java-map (HashMap. {1 2 3 4})) ; #6
   (hash {1 2 3 4}))
;; true

The Java-map example shows entry iteration, `hash` on key-value pairs, `unchecked-add` for accumulation, and `mix-collection-hash` for the final result. section 6.6 section 5.13

How Clojure: The Essential Reference covers it

How deep it goes
Defines the input, signed 32-bit output, dispatch rules, and helper contracts, then illustrates Java interop without fully specifying hashing algorithms.
Examples
Contrasts Java hashCode with hash on numeric and composite keys, then tests ordering and Java-collection interoperability.
What it assumes
Assumes familiarity with Clojure collections and maps; defines hash’s contract while using Java interop in worked examples.
What you can do after
Apply it via Clojure hash and collection-hashing helpers to inspect composite-key behavior and integrate iterable collection hashes.
How it connects
Links hashing to equality, Java hashCode, hash maps, ordered and unordered collections, and unchecked arithmetic.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Clojure: The Essential Reference. The section links point to the parts of the book it draws on.