2012-02-01 89 views
10

檢測對象是否是Clojure中的Java基元數組的最佳方法是什麼?測試對象是否是Clojure中的Java基元數組

我之所以需要這個是做一些特殊處理的基本數組,這可能看起來像:

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

它的代碼相當性能敏感的一塊,所以我寧願避免反光,如果儘可能。

+1

不知道Clojure的代碼是什麼,但是你可以爲每個基元類型創建一個空數組,對這些數組調用getClass()並緩存結果。 Class對象對於每個原始類型的數組都應該是相同的 - 您可以使用object.getClass()比較緩存的對象。(getClass()不應該是一個緩慢的調用) – millimoose 2012-02-01 03:45:15

回答

8

你可以使用反射一次是從名稱獲取類,緩存這一點,然後 其餘比較於

(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 
+0

不錯,就像緩存基本數組類一樣。雖然它確實有點讓我覺得它們還沒有在Java的某個地方定義過! – mikera 2012-02-01 04:26:09

+0

,他們想出了這個名字:「[I」在那...... – 2012-02-01 04:30:11

+3

'「[J''因爲'長'更加可愛,不是嗎?另外,無論誰在'.toString'中提出了無與倫比的開頭括號,都會返回值,只要我知道他們的名字,我的乾草叉就會準備好。它一直讓我失去信任,更不用說[對我的心理的影響](http://xkcd.com/859/)。 (替換所有相關案例的'print-method'可能不可行 - 我目前的直覺是* not *)。 – 2012-02-01 04:51:14

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)))) 
+0

所有的祕密都是裸露的:http://docs.oracle.com/javase/6 /docs/api/java/lang/Class.html – Bill 2012-02-01 04:46:01

4

或純老instance?

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

你使用了什麼別名用於'RT'?你的意思是'(Class/forName「[B」)'對嗎? – 2013-12-21 05:00:22

+0

@DavidJames RT是clojure.lang.RT。 – kotarak 2015-05-07 17:02:33

4

正如指出亞瑟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 []))) 
+1

更簡單:'(def byte-array-class(class(byte-array 0)))'。 (不要強調!) – 2013-12-21 05:02:40

5

要檢查的字節數組,而無需使用反射,你可以這樣做:

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

不完全確定爲什麼,但是您甚至可以用^:const內聯字節數組類型。

2

道具所有其他答案。在這裏它是作爲一襯墊:

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

但這些方法將可能不會在性能上的瓶頸。