从 PersistentQueue 中弹出的元素引用不会立即从队列中删除。这可能导致队列实际包含的对象多于它当前包含的更多情况。
这是因为 PersistentQueue 是通过两个 PersistentVectors 实现的,一个用于头部,一个用于尾部。一旦头部为空,尾部向量将转换为 ChunkedSeq(通过对其进行调用 seq)并放入头部。然而,即使它通过 {{next}} 缩小,ChunkedSeq 也总是保留对起始向量的引用。
示例,使用 clj-memory-meter
`
(require '[clj-memory-meter.core :as mm])
(def q clojure.lang.PersistentQueue/EMPTY)
(def strs (repeatedly 100000 #(String. (.toCharArray "Hello"))))
;; Queue with 100k strings "Hello"
(mm/measure (into q strs))
=> "5.9 MB"
;; Shrink such queue to just 1 element
(nth (iterate pop (into q strs)) 99999)
=> ;; a queue of one element
;; But it still occupies 6 mb
(mm/measure (nth (iterate pop (into q strs)) 99999))
=> "5.9 MB"
`
或许,如果这种行为是预期的,它至少应该反映在文档中?既然 PQ 已经是隐藏的,且文档不足。