简体   繁体   English

将Java集合转换为Clojure数据结构

[英]Converting Java collections to Clojure data structures

I am creating a Clojure interface to a Java API with a method that returns a java.util.LinkedHashSet. 我正在使用返回java.util.LinkedHashSet的方法创建Java API的Clojure接口。

Firstly, is the idiomatic Clojure way of handling this to convert the LinkedHashSet to a clojure data structure? 首先,处理此问题的惯用Clojure方法是将LinkedHashSet转换为clojure数据结构吗?

Secondly, what is the best method for converting Java collections into Clojure data structures? 其次,将Java集合转换为Clojure数据结构的最佳方法是什么?

There are lots of options, since Clojure plays very nicely with Java collections. 有很多选项,因为Clojure与Java集合非常相似。 It depends on exactly what data structure you want to use in Clojure. 它取决于您想要在Clojure中使用的数据结构。

Here's some examples: 以下是一些例子:

;; 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

Regarding when to use each of these, I'd suggest the following advice: 关于何时使用这些,我建议以下建议:

  • If you are trying to wrap a Java library and present a clean Clojure API, then I'd suggest converting to the equivalent Clojure data structures. 如果您正在尝试打包Java库并提供一个干净的Clojure API,那么我建议转换为等效的Clojure数据结构。 This is what Clojure users will expect, and you can hide the potentially messy Java interop details. 这就是Clojure用户期望的,您可以隐藏可能混乱的Java互操作细节。 As a bonus, this will make things immutable so that you don't run the risk of Java collections mutating while you use them. 作为奖励,这将使事情变得不可变,这样您就不会冒着Java集合在使用它们时发生变异的风险。
  • If you just want to use the Java API quickly and efficiently, just use Java interop directly on the Java collections. 如果您只想快速有效地使用Java API,只需直接在Java集合上使用Java interop即可。

The idiomatic way to convert java collections to clojure is to use the (seq) function, which is already called by most functions operating on sequences. 将java集合转换为clojure的惯用方法是使用(seq)函数,该函数已经被大多数在序列上运行的函数调用。

(def s (java.util.LinkedHashSet.))
#'user/s
user> (seq s)
nil
user> (.add s "foo")
true
user> (seq s)
("foo")
user> 

I honestly don't know if there's a universally accepted practice, but here's Chris Houser arguing against Java to Clojure adapters as you break compatibility with the original Java API. 老实说,我不知道是否有一个普遍接受的做法,但这里的克里斯·豪泽主张对Java来Clojure的适配器为你打破与原始的Java API的兼容性。

To perform the translation you asked for, simply use 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"}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM