HashMap

typeremoved v1.12.134added v1.12.116removed v0.0-1798added v0.0-927Edit
satisfies IAssociative ICloneable ICollection ICounted IEditableCollection IEmptyableCollection IEquiv IFn IHash IIterable IKVReduce ILookup IMap IMeta IPrintWithWriter ISeqable ITransientAssociative ITransientCollection ITransientMap IWithMeta

(HashMap. meta count hashobj __hash)

Source code @ clojurescript:src/main/cljs/cljs/core.cljs
(deftype HashMap [meta count hashobj ^:mutable __hash]
  Object
  (toString [coll]
    (pr-str* coll))
  (keys [coll]
    (let [arr (. (-seq coll) -arr)]
      (es6-iterator (prim-seq (.map arr -key (-seq coll))))))
  (entries [coll]
    (es6-entries-iterator (-seq coll)))
  (values [coll]
    (let [arr (. (-seq coll) -arr)]
      (es6-iterator (prim-seq (.map arr -val (-seq coll))))))
  (has [coll k]
    (contains? coll k))
  (get [coll k not-found]
    (-lookup coll k not-found))
  (forEach [coll f]
    (let [xs (-seq coll)]
      (when-not (nil? xs)
        (.forEach (.-arr xs)
          #(f (-val %) (-key %))))))

  IWithMeta
  (-with-meta [coll meta] (HashMap. meta count hashobj __hash))

  IMeta
  (-meta [coll] meta)

  ICloneable
  (-clone [coll] (HashMap. meta count hashobj __hash))

  ICollection
  (-conj [coll entry]
    (if (vector? entry)
      (-assoc coll (-nth entry 0) (-nth entry 1))
      (reduce -conj coll entry)))

  IEmptyableCollection
  (-empty [coll] (with-meta (. HashMap -EMPTY) meta))

  IEquiv
  (-equiv [coll other] (equiv-map coll other))

  IHash
  (-hash [coll] (caching-hash coll hash-unordered-coll __hash))

  ISeqable
  (-seq [coll]
    (when (pos? count)
      (let [hashes (.sort (js-keys hashobj))
            cnt    (alength hashes)
            arr    (array)]
        (loop [i 0]
          (if (< i cnt)
            (let [bckt (unchecked-get hashobj (aget hashes i))
                  len  (alength bckt)]
              (loop [j 0]
                (when (< j len)
                  (do
                    (.push arr (MapEntry. (aget bckt j) (aget bckt (inc j)) nil))
                    (recur (+ j 2)))))
              (recur (inc i)))
            (prim-seq arr))))))

  ICounted
  (-count [coll] count)

  ILookup
  (-lookup [coll k] (-lookup coll k nil))
  (-lookup [coll k not-found]
    (let [bucket (unchecked-get hashobj (hash k))
          i (when bucket (scan-array-equiv 2 k bucket))]
      (if (some? i)
        (aget bucket (inc i))
        not-found)))

  IAssociative
  (-assoc [coll k v]
    (let [h (hash k)
          bucket (unchecked-get hashobj h)]
      (if (some? bucket)
        (let [new-bucket (aclone bucket)
              new-hashobj (gobject/clone hashobj)
              i (scan-array-equiv 2 k new-bucket)]
          (aset new-hashobj h new-bucket)
          (if (some? i)
            (if (identical? v (aget new-bucket (inc i)))
              coll
              (do
                ; found key, replace
                (aset new-bucket (inc i) v)
                (HashMap. meta count new-hashobj nil)))
            (do
              ; did not find key, append
              (.push new-bucket k v)
              (HashMap. meta (inc count) new-hashobj nil))))
        (let [new-hashobj (gobject/clone hashobj)]
          ; did not find bucket
          (unchecked-set new-hashobj h (array k v))
          (HashMap. meta (inc count) new-hashobj nil)))))
  (-contains-key? [coll k]
    (let [bucket (unchecked-get hashobj (hash k))
          i (when bucket (scan-array-equiv 2 k bucket))]
      (if (some? i)
        true
        false)))

  IMap
  (-dissoc [coll k]
    (let [h (hash k)
          bucket (unchecked-get hashobj h)
          i (when bucket (scan-array-equiv 2 k bucket))]
      (if (some? i)
        (let [new-hashobj (gobject/clone hashobj)]
          (if (> 3 (alength bucket))
            (js-delete new-hashobj h)
            (let [new-bucket (aclone bucket)]
              (.splice new-bucket i 2)
              (unchecked-set new-hashobj h new-bucket)))
          (HashMap. meta (dec count) new-hashobj nil))
        ; key not found, return coll unchanged
        coll)))

  IFn
  (-invoke [coll k]
    (-lookup coll k))
  (-invoke [coll k not-found]
    (-lookup coll k not-found))

  IEditableCollection
  (-as-transient [coll]
    coll)

  ITransientCollection
  (-conj! [coll val]
    (-conj coll val))
  (-persistent! [coll]
    coll)

  ITransientAssociative
  (-assoc! [coll key val]
    (-assoc coll key val))

  ITransientMap
  (-dissoc! [coll key]
    (-dissoc coll key))

  IIterable
  (-iterator [coll]
    (let [xs (-seq coll)]
      (if (some? xs)
        (-iterator xs)
        (nil-iter))))

  IKVReduce
  (-kv-reduce [coll f init]
    (let [hashes (.sort (js-keys hashobj))
          ilen   (alength hashes)]
      (loop [i 0 init init]
        (if (< i ilen)
          (let [bckt (unchecked-get hashobj (aget hashes i))
                jlen (alength bckt)
                init (loop [j 0 init init]
                       (if (< j jlen)
                         (let [init (f init (aget bckt j) (aget bckt (inc j)))]
                           (if (reduced? init)
                             init
                             (recur (+ j 2) init)))
                         init))]
            (if (reduced? init)
              @init
              (recur (inc i) init)))
          init))))

  IPrintWithWriter
  (-pr-writer [coll writer opts]
    (print-map coll pr-writer writer opts)))