Clojure:[D和[Ljava.lang.Double ;?]之间有什么区别?

Son*_*oth 5 java clojure

我正在尝试使用本机Java数组做一些事情,我不明白两个双数组实例之间的区别.这与拳击和取消装箱值有关吗?在所有情况下(first...),每个数组的类型都有java.lang.Double类型.Clojure协议似乎对这种区别很敏感.

user> (class (make-array Double/TYPE 3))  ;; [D
user> (class (double-array [1 2 3]))      ;; [D
user> (class (into-array (make-array Double/TYPE 3)))  ;; [Ljava.lang.Double;
user> (class (into-array (double-array [1 2 3])))      ;; [Ljava.lang.Double;
user> (class (into-array (repeat 2 (double-array [1 2 3]) ))) ;; [[D
Run Code Online (Sandbox Code Playgroud)

mik*_*era 8

有两种不同类型的数组需要考虑:

  • [D是一个原始的双数组,相当于Javadouble[]
  • [Ljava.lang.Double;是一个Double 引用数组,相当于Java Double[].

(奇怪的符号是因为这是Java字节码中这些类型的内部表示......在Clojure中暴露它有点奇怪,但你只需要忍受它)

因为它们是不同的类型,所以使用Clojure协议对它们进行不同的处理.

原始双数组通常提供更好的性能,假设您坚持原始的双重操作并避免任何不必要的装箱.您可以将原始数组视为未装箱值的数组,将参考数组视为装箱值数组.

使用参考数组的主要原因是,如果您的值在收到时已经装箱,并且/或者您打算将它们传递给需要装箱值的其他功能或集合.在这种情况下,取消打开双打然后再次打包它们是低效的,因此将它们保持盒装形式是明智的.

FWIW,有几个库可以很容易地使用双数组.特别是你应该看看HipHip(专用数组操作),core.matrix(支持包括双数组在内的许多类型上的向量/矩阵运算)和vectorz-clj(与core.matrix一起工作,将双数组包装为通用向量)