5

我正在使用返回 java.util.LinkedHashSet 的方法创建到 Java API 的 Clojure 接口。

首先,处理此问题的惯用 Clojure 方式是否将 LinkedHashSet 转换为 clojure 数据结构?

其次,将 Java 集合转换为 Clojure 数据结构的最佳方法是什么?

4

3 回答 3

12

有很多选择,因为 Clojure 非常适合 Java 集合。这取决于你想在 Clojure 中使用什么数据结构。

这里有一些例子:

;; create a HashSet
(def a (java.util.HashSet.))
(dotimes [i 10] (.add a i))

;; Get all the values as a sequence 
(seq a)
=> (0 1 2 3 4 5 6 7 8 9)

;; build a new HashSet containing the values from a 
(into #{} a)
#{0 1 2 3 4 5 6 7 8 9}

;; Just use the HashSet directly (high performance, no copy required)
(.contains a 1)
=> true
(.contains a 100)
=> false

关于何时使用这些,我建议以下建议:

  • 如果您尝试包装 Java 库并提供干净的 Clojure API,那么我建议您转换为等效的 Clojure 数据结构。这是 Clojure 用户所期望的,您可以隐藏潜在的混乱 Java 互操作细节。作为奖励,这将使事物不可变,这样您就不会在使用 Java 集合时冒着发生变异的风险。
  • 如果您只想快速有效地使用 Java API,只需在 Java 集合上直接使用 Java 互操作即可。
于 2012-02-14T10:53:48.477 回答
2

将 java 集合转换为 clojure 的惯用方法是使用 (seq) 函数,大多数操作序列的函数已经调用了该函数。

(def s (java.util.LinkedHashSet.))
#'user/s
user> (seq s)
nil
user> (.add s "foo")
true
user> (seq s)
("foo")
user> 
于 2012-02-14T10:52:52.427 回答
2

老实说,我不知道是否存在普遍接受的做法,但这里是 Chris Houser反对Java 到 Clojure 适配器,因为您破坏了与原始 Java API 的兼容性。

要执行您要求的翻译,只需使用into

user=> (import java.util.LinkedHashSet)
java.util.LinkedHashSet
user=> (def x (LinkedHashSet.))
#'user/x
user=> (.add x "test")
true
user=> (def y (into #{} x))
#'user/y
user=> y
#{"test"}
于 2012-02-14T10:53:38.843 回答