I am creating a Clojure interface to a Java API with a method that returns a java.util.LinkedHashSet.
Firstly, is the idiomatic Clojure way of handling this to convert the LinkedHashSet to a clojure data structure?
Secondly, what is the best method for converting Java collections into Clojure data structures?
There are lots of options, since Clojure plays very nicely with Java collections. It depends on exactly what data structure you want to use in 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:
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.
(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.
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"}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With