测试对象是否是Clojure中的Java基元数组

时间:2022-11-30 22:48:30

What's the best way to detect whether an object is a Java primitive array in Clojure?

检测对象是否是Clojure中的Java基元数组的最佳方法是什么?

The reason I need this is to do some special handling for primitive arrays, which might look something like:

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

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

It's in a fairly performance-sensitive piece of code so I'd rather avoid reflection if at all possible.

它是一段性能敏感的代码,所以如果可能的话,我宁愿避免反射。

6 个解决方案

#1


8  

you can use reflection once to get the class from the name, cache this and then compare the rest to that

您可以使用反射一次从名称中获取类,缓存这个,然后将其余的与那个进行比较

(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

#2


7  

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

For particular cases, you could use something like the following:

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

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

#3


5  

To check for a byte array without the use of reflection you can do this:

要在不使用反射的情况下检查字节数组,可以这样做:

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

Not exactly sure why, but you can even inline the byte-array-type with ^:const.

不知道确切的原因,但是你甚至可以内联byte-array-type ^:常量。

#4


4  

Or plain old instance?:

或普通的旧实例吗?

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

#5


4  

As pointed by Arthur Ulfeldt, you can use Class/forName, for example, like here:

正如Arthur Ulfeldt所指出的,您可以使用类/forName,例如:

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

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

If you want to avoid magic strings like "[B" when caching the classes, you can apply class to an existing array object:

如果您想要避免像“[B]”这样的魔法字符串,那么可以将类应用到现有的数组对象:

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

#6


2  

Props to all the other answers. Here it is as a one-liner:

所有其他答案的道具。这是一句俏皮话:

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

For other primitives, refer to http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getName%28%29 (or the java spec). Or just do what Gerrit suggests with (type (xyz-array 0)). Specifically you can use:

对于其他原语,请参考http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getName%28%29(或java规范)。或者按照Gerrit的建议(类型(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

Since performance was mentioned, here's a small benchmark result of running (time (dotimes [_ 500000] (byte-array? x))), and with byte-array-class def'd

由于提到了性能,这里有一个运行的小基准结果(时间(dotimes[_ 500000])(字节数组?)和字节数组类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 = instance? wins

实例?vs类型=实例?赢了

partial vs defn = defn wins

部分vs

but any of these approaches will likely not be a bottleneck in performance.

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

#1


8  

you can use reflection once to get the class from the name, cache this and then compare the rest to that

您可以使用反射一次从名称中获取类,缓存这个,然后将其余的与那个进行比较

(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

#2


7  

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

For particular cases, you could use something like the following:

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

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

#3


5  

To check for a byte array without the use of reflection you can do this:

要在不使用反射的情况下检查字节数组,可以这样做:

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

Not exactly sure why, but you can even inline the byte-array-type with ^:const.

不知道确切的原因,但是你甚至可以内联byte-array-type ^:常量。

#4


4  

Or plain old instance?:

或普通的旧实例吗?

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

#5


4  

As pointed by Arthur Ulfeldt, you can use Class/forName, for example, like here:

正如Arthur Ulfeldt所指出的,您可以使用类/forName,例如:

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

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

If you want to avoid magic strings like "[B" when caching the classes, you can apply class to an existing array object:

如果您想要避免像“[B]”这样的魔法字符串,那么可以将类应用到现有的数组对象:

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

#6


2  

Props to all the other answers. Here it is as a one-liner:

所有其他答案的道具。这是一句俏皮话:

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

For other primitives, refer to http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getName%28%29 (or the java spec). Or just do what Gerrit suggests with (type (xyz-array 0)). Specifically you can use:

对于其他原语,请参考http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getName%28%29(或java规范)。或者按照Gerrit的建议(类型(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

Since performance was mentioned, here's a small benchmark result of running (time (dotimes [_ 500000] (byte-array? x))), and with byte-array-class def'd

由于提到了性能,这里有一个运行的小基准结果(时间(dotimes[_ 500000])(字节数组?)和字节数组类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 = instance? wins

实例?vs类型=实例?赢了

partial vs defn = defn wins

部分vs

but any of these approaches will likely not be a bottleneck in performance.

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