diff --git a/src/jvm/clojure/lang/APersistentSet.java b/src/jvm/clojure/lang/APersistentSet.java index 5e3864fc97..8d5ab0e0f7 100644 --- a/src/jvm/clojure/lang/APersistentSet.java +++ b/src/jvm/clojure/lang/APersistentSet.java @@ -140,19 +140,7 @@ public boolean containsAll(Collection c){ } public Object[] toArray(Object[] a){ - if(a.length >= count()) - { - ISeq s = seq(); - for(int i = 0; s != null; ++i, s = s.next()) - { - a[i] = s.first(); - } - if(a.length > count()) - a[count()] = null; - return a; - } - else - return toArray(); + return RT.seqToPassedArray(seq(), a); } public int size(){ diff --git a/src/jvm/clojure/lang/APersistentVector.java b/src/jvm/clojure/lang/APersistentVector.java index ef73c5bfa5..2b373790ae 100644 --- a/src/jvm/clojure/lang/APersistentVector.java +++ b/src/jvm/clojure/lang/APersistentVector.java @@ -366,19 +366,7 @@ public boolean containsAll(Collection c){ } public Object[] toArray(Object[] a){ - if(a.length >= count()) - { - ISeq s = seq(); - for(int i = 0; s != null; ++i, s = s.next()) - { - a[i] = s.first(); - } - if(a.length > count()) - a[count()] = null; - return a; - } - else - return toArray(); + return RT.seqToPassedArray(seq(), a); } public int size(){ diff --git a/src/jvm/clojure/lang/ASeq.java b/src/jvm/clojure/lang/ASeq.java index e5ae82d89f..5597f5fe52 100644 --- a/src/jvm/clojure/lang/ASeq.java +++ b/src/jvm/clojure/lang/ASeq.java @@ -175,19 +175,7 @@ public boolean containsAll(Collection c){ } public Object[] toArray(Object[] a){ - if(a.length >= count()) - { - ISeq s = seq(); - for(int i = 0; s != null; ++i, s = s.next()) - { - a[i] = s.first(); - } - if(a.length > count()) - a[count()] = null; - return a; - } - else - return toArray(); + return RT.seqToPassedArray(seq(), a); } public int size(){ diff --git a/src/jvm/clojure/lang/LazySeq.java b/src/jvm/clojure/lang/LazySeq.java index 7fc613a8fa..6e9e37c111 100644 --- a/src/jvm/clojure/lang/LazySeq.java +++ b/src/jvm/clojure/lang/LazySeq.java @@ -174,19 +174,7 @@ public boolean containsAll(Collection c){ } public Object[] toArray(Object[] a){ - if(a.length >= count()) - { - ISeq s = seq(); - for(int i = 0; s != null; ++i, s = s.next()) - { - a[i] = s.first(); - } - if(a.length > count()) - a[count()] = null; - return a; - } - else - return toArray(); + return RT.seqToPassedArray(seq(), a); } public int size(){ diff --git a/src/jvm/clojure/lang/PersistentQueue.java b/src/jvm/clojure/lang/PersistentQueue.java index 674fd790bb..fed7e406c5 100644 --- a/src/jvm/clojure/lang/PersistentQueue.java +++ b/src/jvm/clojure/lang/PersistentQueue.java @@ -204,19 +204,7 @@ public boolean containsAll(Collection c){ } public Object[] toArray(Object[] a){ - if(a.length >= count()) - { - ISeq s = seq(); - for(int i = 0; s != null; ++i, s = s.next()) - { - a[i] = s.first(); - } - if(a.length >= count()) - a[count()] = null; - return a; - } - else - return toArray(); + return RT.seqToPassedArray(seq(), a); } public int size(){ diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index 0c9cb55eb9..3f77ad245a 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -1570,6 +1570,21 @@ static public Object[] seqToArray(ISeq seq){ return ret; } + // supports java Collection.toArray(T[]) + static public Object[] seqToPassedArray(ISeq seq, Object[] passed){ + Object[] dest = passed; + int len = count(seq); + if (len > dest.length) { + dest = (Object[]) Array.newInstance(passed.getClass().getComponentType(), len); + } + for(int i = 0; seq != null; ++i, seq = seq.next()) + dest[i] = seq.first(); + if (len < passed.length) { + dest[len] = null; + } + return dest; + } + static public Object seqToTypedArray(ISeq seq) { Class type = (seq != null) ? seq.first().getClass() : Object.class; return seqToTypedArray(type, seq); diff --git a/test/clojure/test_clojure/java_interop.clj b/test/clojure/test_clojure/java_interop.clj index 059ef11511..08c3db2901 100644 --- a/test/clojure/test_clojure/java_interop.clj +++ b/test/clojure/test_clojure/java_interop.clj @@ -273,6 +273,29 @@ (to-array []) (to-array [1 2 3]) )) +(defn queue [& contents] + (apply conj (clojure.lang.PersistentQueue/EMPTY) contents)) + +(defn array-typed-equals [expected actual] + (and (= (class expected) (class actual)) + (java.util.Arrays/equals expected actual))) + +(defmacro test-to-passed-array-for [collection-type] + `(deftest ~(symbol (str "test-to-passed-array-for-" collection-type)) + (let [string-array# (make-array String 5) + shorter# (~collection-type "1" "2" "3") + same-length# (~collection-type "1" "2" "3" "4" "5") + longer# (~collection-type "1" "2" "3" "4" "5" "6")] + (are [expected actual] (array-typed-equals expected actual) + (into-array String ["1" "2" "3" nil nil]) (.toArray shorter# string-array#) + (into-array String ["1" "2" "3" "4" "5"]) (.toArray same-length# string-array#) + (into-array String ["1" "2" "3" "4" "5" "6"]) (.toArray longer# string-array#))))) + + +(test-to-passed-array-for vector) +(test-to-passed-array-for list) +(test-to-passed-array-for hash-set) +(test-to-passed-array-for queue) (deftest test-into-array ; compatible types only