我试图在MapDB中直接使用Clojure的hashmap,并遇到了奇怪的行为。我查看了Clojure和MapDB源代码,无法理解问题所在。
首先,一切看起来都很好:
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!然后我再次尝试访问这些数据:
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为什么相同的关键字与=不同?有什么奇怪的引用问题发生了吗?
发布于 2015-02-26 12:00:18
这个问题是由关键字相等的工作方式引起的。查看函数的实现,我们可以看到,由于关键字不是clojure.lang.Number或clojure.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中使用它。
(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实例相同的对象。因此,平等检查将正常工作。
https://stackoverflow.com/questions/28719945
复制相似问题