2010-11-30 29 views
37

Quel est le moyen Clojure-idiomatiques pour convertir une structure de données à une collection Java, plus précisément:Conversion des structures de données Clojure aux collections Java

  • [] à un java.util.ArrayList
  • {} à un java.util.HashMap
  • #{} à un
  • () à un

Existe-t-il une bibliothèque clojure.contrib pour cela? Pour aider Clojure dans mon organisation, j'envisage d'écrire une suite de tests unitaires pour un serveur REST Java dans Clojure. J'ai écrit une partie de la suite dans Scala, mais je pense que Clojure pourrait être meilleur parce que le support de la macro réduira beaucoup le code standard (j'ai besoin de tester des douzaines d'appels de service REST similaires). J'utilise EasyMock pour simuler les connexions à la base de données (existe-t-il un meilleur moyen?) Et mes méthodes simulées doivent renvoyer java.util.List<java.util.Map<String, Object>> éléments (représentant des ensembles de lignes de base de données) aux appelants. Je passerais dans une structure [{ "first_name" "Joe" "last_name" "Smith" "date_of_birth" (date "1960-06-13") ... } ...] à ma maquette et la convertirais à la collection Java requise afin qu'elle puisse être retournée à l'appelant dans le format attendu.

+6

Si les méthodes doivent revenir 'java.util.List', alors il n'y a pas besoin de convertir depuis un clojure vector * est un * 'List'. Vous devez uniquement convertir si le type requis est d'une classe d'implémentation spécifique, par ex. 'ArrayList'. –

Répondre

65

vecteur Clojure, set et classes de liste implémenter l'interface java.util.Collection et ArrayList, HashSet et LinkedList peut prendre un argument du constructeur java.util.Collection. Ainsi, vous pouvez simplement faire:

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

De même, Clojure classe carte implémente l'interface java.util.Map et HashMap prend un argument constructeur java.util.Map. Alors:

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

Vous pouvez aussi faire l'inverse et il est beaucoup plus facile:

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} 
+0

Je ne le savais pas. C'est parfait. Merci. – Ralph

+2

Juste au cas où il est nécessaire de transformer des clés de mot-clé dans une carte Clojure en chaînes, vous pouvez utiliser "stringify-keys" qui peut également être trouvé dans clojure.walk. –