从PersistentQueue中弹出的元素引用不会立即从队列中删除。这可能导致队列保留了比它当前包含的更多对象的情况。
这是因为在PersistentQueue中使用两个PersistentVectors实现,一个用于head,一个用于tail。一旦head为空,尾向量就会被转换为ChunkedSeq(通过在它上调用seq),然后放入head。然而,ChunkedSeq始终保留对整个起始向量的引用,即使它通过{{next}}进行收缩。
示例,使用clj-memory-meter
`
(require '[clj-memory-meter.core :as mm])
(def q clojure.lang.PersistentQueue/EMPTY)
(def strs (repeatedly 100000 #(String. (.toCharArray "Hello"))))
;; 使用100k个"Hello"字符串创建队列
(mm/measure (into q strs))
=> "5.9 MB"
;; 缩小此队列到仅剩一个元素
(nth (iterate pop (into q strs)) 99999)
=> ;; 一个元素队列
;; 但它仍然占用6 MB
(mm/measure (nth (iterate pop (into q strs)) 99999))
=> "5.9 MB"
`
也许,如果这种行为是预期的,至少应该在文档中反映出来?鉴于PQ已经隐藏且未充分记录。