2012-02-14 21 views
5

Estoy creando una interfaz Clojure para una API Java con un método que devuelve un java.util.LinkedHashSet.Conversión de colecciones Java en estructuras de datos Clojure

En primer lugar, ¿es la manera idiomática de Clojure de manejar esto convertir el LinkedHashSet a una estructura de datos clojure?

En segundo lugar, ¿cuál es el mejor método para convertir colecciones Java en estructuras de datos Clojure?

Respuesta

12

Hay un montón de opciones, desde Clojure juega muy bien con las colecciones de Java. Depende exactamente de qué estructura de datos desee utilizar en Clojure.

He aquí algunos ejemplos:

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

En cuanto a cuándo utilizar cada uno de ellos, me gustaría sugerir el siguiente consejo:

  • Si usted está tratando de envolver una biblioteca de Java y presentar una limpia Clojure API, entonces sugeriría convertir a las estructuras de datos Clojure equivalentes. Esto es lo que los usuarios de Clojure esperarán, y usted puede ocultar los detalles de interoperabilidad de Java potencialmente desordenados. Como beneficio adicional, esto hará que las cosas sean inmutables para que no corras el riesgo de que las colecciones de Java muten mientras las usas.
  • Si solo desea utilizar la API de Java de forma rápida y eficiente, simplemente utilice la interoperabilidad de Java directamente en las colecciones de Java.
2

La forma idiomática de convertir colecciones java a clojure es usar la función (seq), que ya es llamada por la mayoría de las funciones que operan en secuencias.

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

Sinceramente, no sé si hay una práctica universalmente aceptada, pero aquí está Chris Houser arguing contra Java para adaptadores de Clojure como se rompe la compatibilidad con la API de Java originales.

Para llevar a cabo la traducción que solicitó, basta con utilizar 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"} 
Cuestiones relacionadas