2009-07-10 21 views
54

Estoy implementando una interfaz que tiene una funcionalidad similar a una tabla que puede contener un tipo de objetos. La interfaz especifica la siguiente función:¿Cómo convierto Double [] a double []?

double[] getDoubles(int columnIndex); 

Dónde estoy confundido es que en mi aplicación, Estoy almacenando los datos de la tabla en una matriz 2D Object (Object[][] data). Cuando necesito para devolver los valores, quiero hacer lo siguiente (se supone que getDoubles() solamente serán llamados en una columna que contiene dobles, por lo que no habrá ClassCastExceptions):

double[] getDoubles(int columnIndex) { 
    return (double[]) data[columnIndex]; 
} 

Pero - doesn Java no permita Object[] ser lanzado a double[]. Enviarlo a Double[] está bien porque Double es un objeto y no una primitiva, pero mi interfaz especifica que los datos se devolverán como double[].

así que tengo dos preguntas:

  1. ¿Hay alguna manera de obtener los datos de las columnas de la tabla Object[][] y devolver la matriz de primitivas?
  2. Si cambio la interfaz para devolver Double[], ¿habrá algún impacto en el rendimiento?
+0

¿Por qué necesita tener datos como Objeto [] []? – notnoop

+0

La tabla puede almacenar cualquier tipo de datos: cadenas, dobles, enteros, otros tipos, etc. – Brian

+0

Entonces, ¿cómo se puede asegurar que la matriz en el columnIndex contiene solo Dobles/Dobles? – notnoop

Respuesta

31

Desafortunadamente tendrá que recorrer toda la lista y desempacar el Double si desea convertirlo en un double[].

En lo que respecta al rendimiento, hay un cierto tiempo asociado con las primitivas de boxeo y unboxing en Java. Si el conjunto es lo suficientemente pequeño, no verá ningún problema de rendimiento.

+4

Aunque no es directamente aplicable, las pruebas en C# al ordenar matrices grandes (un millón de elementos) con tipos primitivos frente a cajas mostraron que el tipo primitivo es 3 veces más rápido. Menciono esto porque ilustra que el costo del auto boxing/unboxing puede ser significativo. – cletus

+0

Wow. Eso es mucho más significativo de lo que hubiera esperado. Sin embargo, no consideraría un millón un conjunto pequeño. – jjnguy

3

Si desea devolver un double[], deberá crear un new double[], rellenarlo y devolverlo.

Esa puede ser una buena decisión de arquitectura. Primero, no tiene mucho sentido lanzar un Object[] a un Double[]; en realidad no es una matriz de Double porque podría haber Object s en ella también. En segundo lugar, si devuelve la matriz directamente, el código de usuario puede modificarla y alterar la estructura interna de su objeto.

El principal impacto en el rendimiento sería devolver una matriz de double[], debido al desempaquetado y al costo de asignación.

7

Puede usar a para cada bucle para construir una matriz temporal del mismo tamaño y luego moldear cada elemento individual para duplicarlo pero hacerlo en la matriz.

SO:

double[] tempArray = new double[data[columnIndex].length]; 
int i = 0; 
for(Double d : (Double) data[columnIndex]) { 
    tempArray[i] = (double) d; 
    i++; 
} 

Por favor, corríjanme si estoy totalmente equivocado aquí.

+0

Esta es en realidad una solución más simple que las otras – Ryde

76

Si no le molesta usar una biblioteca de terceros, commons-lang tiene el tipo ArrayUtils con varios métodos de manipulación.

Double[] doubles; 
... 
double[] d = ArrayUtils.toPrimitive(doubles); 

También existe el método complementario

doubles = ArrayUtils.toObject(d); 

Editar: Para responder el resto de la pregunta. Habrá algunos gastos generales para hacer esto, pero a menos que la matriz sea realmente grande, no debes preocuparte por ello. Pruébelo primero para ver si es un problema antes de refactorizar.

Implementar el método que realmente había preguntado daría algo como esto.

double[] getDoubles(int columnIndex) { 
    return ArrayUtils.toPrimitive(data[columnIndex]); 
} 
+0

Gracias por la información que tiene la funcionalidad commons-lang, será muy útil en el futuro si decido ir con cualquier biblioteca de terceros – Brian

+0

Prefiero esto a la respuesta de dando vueltas. Es mucho mejor usar una API de terceros para un código repetitivo como este – Richard

+5

usando libs de terceros que pueden quedar bien (después de todo, un código de una línea parece mucho mejor que un ciclo feo ...) pero la implementación no es diferente de una conversión manual de doble a doble. ¡Peor!Incluso hay un operador ternario para cada iteración que puede resultar en un procesamiento aún mayor de la computadora. Mi punto es que "preferir" una solución debería considerar el rendimiento y la utilidad sobre la estética del código. :) mi 2c. –

0

Me segundos los ArrayUtils responder y añadir que el 1,5 autoboxing documentation (via) revela un poco que no hay manera de orden interna:

no hay conversión permitida de tipo de matriz SC [] para array TC tipo [] si no hay conversión permitido que no sea una conversión de cadenas de SC a TC

1

no tengo nada que añadir a la pregunta real más allá de lo jjnguy y Eric K dijo oslow.

Pero solo una nota al margen: Usted menciona el envío de una matriz de Objetos a una matriz Doble. Lo siguiente NO funcionará:

Object[] oa=new Object[3]; 
oa[0]=new Double("1.0"); 
oa[1]=new Double("2.0"); 
oa[2]=new Double("3.0"); 
Double[] da=(Double[])oa; 

La última línea generará una excepción de clase. Aunque cada elemento de la matriz es de hecho un doble, la matriz se creó como una matriz de objetos, no una matriz de dobles, por lo que el yeso no es válido.

32

En Java 8, esto es de una sola línea:

Double[] boxed = new Double[] { 1.0, 2.0, 3.0 }; 
double[] unboxed = Stream.of(boxed).mapToDouble(Double::doubleValue).toArray(); 

Tenga en cuenta que esto todavía itera sobre la matriz original y crea una nueva.

+0

Esto es lo que estaba buscando! –

1

puede utilizar el ArrayUtils para convertir

Double[] d; // initialise 
double[] array = ArrayUtils.toPrimitive(d); 

No hay necesidad de bucle todos los datos.