测试对象是否是Clojure中的Java原始数组

时间:2012-02-01 03:34:39

标签: arrays reflection clojure primitive-types

在Clojure中检测对象是否是Java原始数组的最佳方法是什么?

我需要这个的原因是对原始数组做一些特殊的处理,它可能看起来像:

  (if (byte-array? object)
    (handle-byte-array object))

这是一段性能相当敏感的代码,所以我宁愿尽量避免反思。

7 个答案:

答案 0 :(得分:9)

你可以使用反射一次从名称中获取类,然后缓存它 比较其余的

(def array-of-ints-type (Class/forName "[I"))
(def array-of-bytes-type (Class/forName "[B")) 
...

(= (type (into-array Integer/TYPE [1 3 4])) array-of-ints-type)
true

答案 1 :(得分:7)

(defn primitive-array? [o]
  (let [c (class o)]
    (and (.isArray c)
         (.. c getComponentType isPrimitive))))

对于特定情况,您可以使用以下内容:

(defn long-array? [o]
  (let [c (class o)]
    (and (.isArray c)
         (identical? (.getComponentType c) Long/TYPE))))

答案 2 :(得分:6)

要在不使用反射的情况下检查字节数组,可以执行以下操作:

(def ^:const byte-array-type (type (byte-array 0)))
(defn bytes? [x] (= (type x) byte-array-type))

不完全确定原因,但您甚至可以使用^:const内联字节数组类型。

答案 3 :(得分:5)

正如Arthur Ulfeldt指出的那样,你可以使用Class/forName,例如,像这里:

(def byte_array_class (Class/forName "[B"))

(defn byte-array? [arr] (instance? byte_array_class arr))

如果要在缓存类时避免使用"[B"之类的魔术字符串,可以将class应用于现有数组对象:

(def byte_array_class (class (byte-array [])))

答案 4 :(得分:4)

或普通的instance?

(instance? (RT/classForName "[B") thing)

答案 5 :(得分:3)

支持所有其他答案。这是一个单行:

(def byte-array? (partial instance? (Class/forName "[B")))

对于其他原语,请参阅http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getName%28%29(或java规范)。或者只是做Gerrit对(type (xyz-array 0))的建议。具体来说,您可以使用:

"[Z" boolean array
"[B" byte array
"[C" char array
"[D" double array
"[F" float array
"[I" integer array
"[J" long array
"[S" short array

由于提到了效果,这是运行(time (dotimes [_ 500000] (byte-array? x)))byte-array-class def' d

的小基准测试结果
(def byte-array? (partial instance? (Class/forName "[B")))
78.518335 msecs
(defn byte-array? [obj] (instance? byte-array-class obj))
34.879537 msecs
(defn byte-array? [obj] (= (type obj) byte-array-class))
49.68781 msecs

instance? vs type =实例?胜

partial vs defn = defn wins

但这些方法中的任何一种都可能不会成为性能瓶颈。

答案 6 :(得分:0)

从Clojure 1.9开始,您可以使用bytes? bytes? doc link