首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在MapDB中使用Clojure的数据结构

在MapDB中使用Clojure的数据结构
EN

Stack Overflow用户
提问于 2015-02-25 13:13:42
回答 1查看 494关注 0票数 3

我试图在MapDB中直接使用Clojure的hashmap,并遇到了奇怪的行为。我查看了Clojure和MapDB源代码,无法理解问题所在。

首先,一切看起来都很好:

代码语言:javascript
复制
lein try org.mapdb/mapdb "1.0.6"

; defining a db for the first time
(import [org.mapdb DB DBMaker])
(defonce db (-> (DBMaker/newFileDB (java.io.File. "/tmp/mapdb"))
                .closeOnJvmShutdown
                .compressionEnable
                .make))
(defonce fruits (.getTreeMap db "fruits-store"))
(do (.put fruits :banana {:qty 2}) (.commit db))

(get fruits :banana)
=> {:qty 2}
(:qty (get fruits :banana))
=> 2
(first (keys (get fruits :banana)))
=> :qty
(= :qty (first (keys (get fruits :banana))))
=> true

CTRL-D
=> Bye for now!

然后我再次尝试访问这些数据:

代码语言:javascript
复制
lein try org.mapdb/mapdb "1.0.6"

; loading previsously created db
(import [org.mapdb DB DBMaker])
(defonce db (-> (DBMaker/newFileDB (java.io.File. "/tmp/mapdb"))
                .closeOnJvmShutdown
                .compressionEnable
                .make))
(defonce fruits (.getTreeMap db "fruits-store"))

(get fruits :banana)
=> {:qty 2}
(:qty (get fruits :banana))
=> nil
(first (keys (get fruits :banana)))
=> :qty
(= :qty (first (keys (get fruits :banana))))
=> false
(class (first (keys (get fruits :banana))))
=> clojure.lang.Keyword

为什么相同的关键字与=不同?有什么奇怪的引用问题发生了吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-02-26 12:00:18

这个问题是由关键字相等的工作方式引起的。查看函数的实现,我们可以看到,由于关键字不是clojure.lang.Numberclojure.lang.IPersistentCollection,所以它们的相等性是根据Object.equals方法确定的。在浏览clojure.lang.Keyword时,我们了解到关键字不覆盖Object.equals,因此两个关键字是相等的当且仅当它们是同一个对象。

MapDB的默认序列化程序是org.mapdb.SerializerPojo,它是org.mapdb.SerializerBase的子类。在其文件中,我们可以看到

序列化器,它使用“头字节”来序列化/反序列化“java.lang”和“java.util”包中的大多数类。

不幸的是,它在clojure.lang类中不能很好地工作;它没有保留关键字的标识,从而破坏了等式。为了修复它,让我们尝试使用EDN格式-alternatively编写我们自己的-alternatively,您可以考虑,比方说,尼皮-and在我们的MapDB中使用它。

代码语言:javascript
复制
(require '[clojure.edn :as edn])

(deftype EDNSeralizer []
  ;; See docs of org.mapdb.Serializer for semantics.
  org.mapdb.Serializer
  (fixedSize [_]
    -1)
  (serialize [_ out obj]
    (.writeUTF out (pr-str obj)))
  (deserialize [_ in available]
    (edn/read-string (.readUTF in)))
  ;; MapDB expects serializers to be serializable.
  java.io.Serializable)

(def edn-serializer (EDNSeralizer.))

(import [org.mapdb DB DBMaker])
(def db (.. (DBMaker/newFileDB (java.io.File. "/tmp/mapdb"))
            closeOnJvmShutdown
            compressionEnable
            make))

(def more-fruits (.. db
                     (createTreeMap "more-fruits")
                     (valueSerializer (EDNSeralizer.))
                     (makeOrGet)))
(.put more-fruits :banana {:qty 2})
(.commit db)

一旦more-fruits树映射在定义了EDNSeralizer的JVM中重新打开,存储在其中的:qty对象将是与任何其他:qty实例相同的对象。因此,平等检查将正常工作。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28719945

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档