2012-02-14 42 views
5

我正在使用返回java.util.LinkedHashSet的方法创建Java API的Clojure接口。将Java集合转换为Clojure数据结构

首先,是处理这种将LinkedHashSet转换为clojure数据结构的惯用Clojure方式?

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

回答

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 interop即可。
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> 
2

老实说,我不知道是否有一个普遍接受的做法,但这里的克里斯·豪泽arguing针对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"}