Проверка того, является ли объект примитивным массивом Java в Clojure - PullRequest
11 голосов
/ 01 февраля 2012

Каков наилучший способ определить, является ли объект массивом примитивов Java в Clojure?

Причина, по которой мне это нужно, заключается в том, чтобы выполнить некоторую специальную обработку для примитивных массивов, которая может выглядеть примерно так:

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

Это довольно чувствительный к производительности фрагмент кода, поэтому я бы предпочел избегать рефлексии, если это вообще возможно.

Ответы [ 7 ]

9 голосов
/ 01 февраля 2012

вы можете использовать отражение один раз, чтобы получить класс из имени, кэшировать его, а затем сравнить остальные с этим

(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
7 голосов
/ 01 февраля 2012
(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))))
6 голосов
/ 17 декабря 2013

Чтобы проверить байтовый массив без использования отражения, вы можете сделать это:

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

Не совсем уверен, почему, но вы можете даже встроить тип байтового массива с помощью ^:const.

5 голосов
/ 22 июня 2012

Как указал Артур Ульфельдт, вы можете использовать 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 голосов
/ 01 февраля 2012

Или обычный старый instance?:

(instance? (RT/classForName "[B") thing)
3 голосов
/ 18 июня 2015

Подсказки ко всем остальным ответам.Здесь это в виде одной строки:

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

Для других примитивов, обратитесь к http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getName%28%29 (или спецификации Java).Или просто сделайте то, что предлагает Геррит с (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?против type = экземпляр?wins

partial против defn = defn wins

, но любой из этих подходов, скорее всего, не будет узким местом в производительности.

0 голосов
/ 13 февраля 2019

Начиная с Clojure 1.9, вы можете использовать bytes? байтов? ссылка на документ

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...