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

43

如何以Clojure的惯用方式将数据结构转换为Java集合,具体地:

  • [] 转换为 java.util.ArrayList
  • {} 转换为 java.util.HashMap
  • #{} 转换为 java.util.HashSet
  • () 转换为 java.util.LinkedList

是否有 clojure.contrib 库可以做到这一点?

应用场景:为了更好地引入 Clojure 到我的组织中,我正在考虑为一个全 Java REST 服务器编写一个单元测试套件。我已经使用 Scala 编写了部分测试套件,但是我认为 Clojure 可能更好,因为宏支持能够减少大量样板代码(我需要测试几十个类似的 REST 服务调用)。

我正在使用 EasyMock 模拟数据库连接(是否有更好的方法?),我的模拟方法需要返回 java.util.List<java.util.Map<String, Object>>类型的项目(表示数据库结果集)给调用方。我将传入一个[{ "first_name" "Joe" "last_name" "Smith" "date_of_birth" (date "1960-06-13") ... } ...]结构到我的模拟函数中,并将其转换为所需的 Java 集合,以便以预期的格式返回给调用方。


6
如果方法需要返回 java.util.List,那么不需要进行转换,因为Clojure向量 就是 List。只有在需要特定实现类,例如 ArrayList 时才需要转换。 - Alex Taggart
1个回答

75

Clojure中的向量(vector)、集合(set)和列表(list)类实现了java.util.Collection接口,且ArrayListHashSetLinkedList可以使用java.util.Collection构造函数参数。因此,您可以简单地执行以下操作:

user=> (java.util.ArrayList. [1 2 3])
#<ArrayList [1, 2, 3]>
user=> (.get (java.util.ArrayList. [1 2 3]) 0)
1

同样地,Clojure的map类实现了java.util.Map接口,HashMap接受一个java.util.Map构造函数参数。因此:

user=> (java.util.HashMap. {"a" 1 "b" 2})
#<HashMap {b=2, a=1}>
user=> (.get (java.util.HashMap. {"a" 1 "b" 2}) "a")
1

你也可以做相反的操作,而且相对更容易:

ser=> (into [] (java.util.ArrayList. [1 2 3]))
[1 2 3]
user=> (into #{} (java.util.HashSet. #{1 2 3}))
#{1 2 3}
user=> (into '() (java.util.LinkedList. '(1 2 3)))
(3 2 1)
user=> (into {} (java.util.HashMap. {:a 1 :b 2}))
{:b 2, :a 1}

3
如果需要将Clojure地图中的关键字键转换为字符串,可以使用"stringify-keys",它也可以在clojure.walk中找到。 - Andre Steingress

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接