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

发布于 2024-12-29 23:12:12 字数 210 浏览 4 评论 0原文

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

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

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

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

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

我们的影子 2025-01-05 23:12:12

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

(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

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
鹿! 2025-01-05 23:12:12
(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))))
(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))))
入画浅相思 2025-01-05 23:12:12

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

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

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

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.

毁虫ゝ 2025-01-05 23:12:12

还是普通的旧实例?

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

Or plain old instance?:

(instance? (RT/classForName "[B") thing)
三生池水覆流年 2025-01-05 23:12:12

正如 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 [])))

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

(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:

(def byte_array_class (class (byte-array [])))
洒一地阳光 2025-01-05 23:12:12

支持所有其他答案。这里只是简单介绍一下:

(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

实例? vs 类型 = 实例?获胜

partialdefn = defn 获胜,

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

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:

"[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

(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

partial vs defn = defn wins

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

不弃不离 2025-01-05 23:12:12

从 Clojure 1.9 开始,您可以使用 bytes? 字节?文档链接

Since Clojure 1.9, you can use bytes? bytes? doc link

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文