2011-08-19 10 views
36

¿Cómo puedo llenar una matriz multidimensional en Java sin utilizar un bucle? He intentado:Arrays.fill con matriz multidimensional en Java

double[][] arr = new double[20][4]; 
Arrays.fill(arr, 0); 

Esto se traduce en java.lang.ArrayStoreException: java.lang.Double

Gracias de antemano!

+2

pero ¿por qué no utilizar un bucle? –

+2

@Caroline: si está intentando inicializar el 2d array con 0, no necesita hacerlo ya que ya está inicializado con 0 cuando asigna el array, y no puede inicializar ningún array sin usar un loop. Puede simplemente ocultar el array en una función como lo hace Arrays.fill. – Emil

+1

Hola chicos, no lo exageren ahora. Todo lo que quería era algún método en Java API para inicializar matrices multidimensionales a algún valor predeterminado en un solo paso. Eso es lo que quería decir sin un bucle. –

Respuesta

48
double[][] arr = new double[20][4]; 
Arrays.fill(arr[0], 0); 
Arrays.fill(arr[1], 0); 
Arrays.fill(arr[2], 0); 
Arrays.fill(arr[3], 0); 
Arrays.fill(arr[4], 0); 
Arrays.fill(arr[5], 0); 
Arrays.fill(arr[6], 0); 
Arrays.fill(arr[7], 0); 
Arrays.fill(arr[8], 0); 
Arrays.fill(arr[9], 0); 
Arrays.fill(arr[10], 0); 
Arrays.fill(arr[11], 0); 
Arrays.fill(arr[12], 0); 
Arrays.fill(arr[13], 0); 
Arrays.fill(arr[14], 0); 
Arrays.fill(arr[15], 0); 
Arrays.fill(arr[16], 0); 
Arrays.fill(arr[17], 0); 
Arrays.fill(arr[18], 0); 
Arrays.fill(arr[19], 0); 
+3

Hola. Solo me interesa saber por qué sugieres esta solución y no un clásico "para". ¿Hay una motivación? ¡Gracias! – Maverik

+61

Debido a las siguientes palabras en la pregunta: "sin usar un bucle". Mi solución es claramente ridícula, pero responde la pregunta correctamente. – trojanfoe

+2

Lo sentimos, perdimos el "sin usar un bucle" del OP: eliminé mi voto negativo. Tal vez debería haber hecho una observación en su respuesta que la sugerencia no debe tomarse demasiado en serio. –

69

Esto se debe a una double[][] es una matriz de double[] que no se puede asignar a 0.0 (sería como hacer double[] vector = 0.0). De hecho, Java no tiene matrices multidimensionales verdaderas.

Si llega el caso, 0.0 es el valor por defecto en dobles en Java, por lo tanto la matriz en realidad ya se rellenan con ceros cuando se obtiene a partir new. Sin embargo, si desea llenarlo con, digamos, 1.0, puede hacer lo siguiente:

No creo que la API proporcione un método para resolver esto sin utilizar un bucle. Sin embargo, es bastante simple hacerlo con un bucle for-each.

double[][] matrix = new double[20][4]; 

// Fill each row with 1.0 
for (double[] row: matrix) 
    Arrays.fill(row, 1.0); 
+0

Esto es suficiente también 'Arrays.fill (arr, 0d); 'o' Arrays.fill (arr, (double) 0); ' –

+2

Obtengo' Excepción en el hilo "main" java.lang.ArrayStoreException: java.lang.Double' a menos que haga un bucle sobre las filas. – aioobe

+0

¿Por qué no intentas entender esta respuesta? ¡En java (y C y C++) no hay matrices multidimensionales! Su matriz es una matriz unidimensional simple, donde cada "campo" es nuevamente una matriz de una dimensión. Su llamada a Arrays.fill() intenta colocar un _int_ (para tener una doble escritura 0.0 y no simplemente 0) en la "matriz", que no funciona. –

3

cómo puedo llenar una matriz multidimensional en Java sin necesidad de utilizar un bucle?

matrices multidimensionales son sólo arreglos de arreglos y fill(...) no comprueba el tipo de la matriz y el valor que se pasa en (esta responsabilidad está sobre el desarrollador).

Por lo tanto, no puede llenar una matriz multidimensional razonablemente bien sin utilizar un bucle.

Tenga en cuenta que, a diferencia de los lenguajes como C o C++, las matrices de Java son objetos y en las matrices multidimensionales todos menos el último nivel contienen referencias a otros objetos Array. No estoy 100% seguro de esto, pero lo más probable es que se distribuyan en la memoria, por lo que no se puede simplemente llenar un bloque contiguo sin un bucle, como C/C++ le permite hacer.

7

El OP preguntó cómo resolver este problema sin un bucle! Por alguna razón, está de moda en estos días evitar los bucles. ¿Por qué es esto? Probablemente se dé cuenta de que el uso de map, reduce, filter y amigos, y métodos como each ocultan bucles y reducen el verbo del programa y son geniales. Lo mismo ocurre con las tuberías realmente dulces de Unix. O el código jQuery. Las cosas se ven muy bien sin bucles.

¿Pero Java tiene un método map? No realmente, pero podríamos definir uno con una interfaz Function con un método eval o exec. No es demasiado difícil y sería un buen ejercicio. Puede ser costoso y no se usa en la práctica.

Otra forma de hacerlo sin un bucle es utilizar recursividad de cola. Sí, es algo tonto y nadie lo usaría en la práctica tampoco, pero muestra, tal vez, que los bucles están bien en este caso.Sin embargo, sólo para mostrar "otra libre de bucles ejemplo" y para divertirse, aquí está:

import java.util.Arrays; 
public class FillExample { 
    private static void fillRowsWithZeros(double[][] a, int rows, int cols) { 
     if (rows >= 0) { 
      double[] row = new double[cols]; 
      Arrays.fill(row, 0.0); 
      a[rows] = row; 
      fillRowsWithZeros(a, rows - 1, cols); 
     } 
    } 

    public static void main(String[] args) { 
     double[][] arr = new double[20][4]; 
     fillRowsWithZeros(arr, arr.length - 1, arr[0].length); 
     System.out.println(Arrays.deepToString(arr)); 
    } 
} 

No es bonita, pero en respuesta a la pregunta de la OP, no hay lazos explícitos.

+0

+1, no para la solución, pero para una muy buena respuesta – Dragon8

+0

¡Gracias por todas sus soluciones! ¿La razón por la que no quiero usar un bucle? Estaba buscando una solución simple para generar una matriz de ceros n-por-n como en MATLAB. – Caroline

+0

Esto aún puede causar un desbordamiento de pila, ya que Java no tiene soporte de recursividad de cola, por lo que los bucles definitivamente> recurrencia. – mc10

1

Como una extensión de la respuesta, encontré esta publicación, pero estaba buscando llenar una matriz de 4 dimensiones. El ejemplo original es solo una matriz bidimensional, pero la pregunta dice "multidimensional". No quería publicar una nueva pregunta para esto ...

Puede usar el mismo método, pero debe anidarlos para que eventualmente llegue a una única matriz dimensional.

fourDArray = new float[10][10][10][1]; 
// Fill each row with null 
for (float[][][] row: fourDArray) 
{ 
    for (float[][] innerRow: row) 
    { 
     for (float[] innerInnerRow: innerRow) 
     { 
     Arrays.fill(innerInnerRow, -1000); 
     } 
    } 
}; 
-5
Arrays.fill(arr, new double[4]); 
+1

Esta línea hace que cada fila se refiera al mismo bloque de memoria, es decir, al cambiar arr [1] [5] también cambiará arr [100] [5]. –

0

no vamos todos a veces me gustaría que hubiese un
<T>void java.util.Arrays.deepFill(T[]…multiDimensional). Los problemas comienzan con
Object threeByThree[][] = new Object[3][3];
threeByThree[1] = null; y
threeByThree[2][1] = new int[]{42}; siendo perfectamente legal.
(Si sólo se Object twoDim[]final[] era legal y bien definido ...)
(Utilizando uno de los métodos públicos desde abajo mantiene bucles a partir del código fuente de la llamada.
Si usted insiste en el uso de ningún bucle en absoluto, sustituir los bucles y la llamada a Arrays.fill() (!), utilizando la recursividad.)

/** Fills matrix {@code m} with {@code value}. 
* @return {@code m}'s dimensionality. 
* @throws java.lang.ArrayStoreException if the component type 
* of a subarray of non-zero length at the bottom level 
* doesn't agree with {@code value}'s type. */ 
public static <T>int deepFill(Object[] m, T value) { 
    Class<?> components; 
    if (null == m || 
     null == (components = m.getClass().getComponentType())) 
     return 0; 
    int dim = 0; 
    do 
     dim++; 
    while (null != (components = components.getComponentType())); 
    filler((Object[][])m, value, dim); 
    return dim; 
} 
/** Fills matrix {@code m} with {@code value}. 
* @throws java.lang.ArrayStoreException if the component type 
* of a subarray of non-zero length at level {@code dimensions} 
* doesn't agree with {@code value}'s type. */ 
public static <T>void fill(Object[] m, T value, int dimensions) { 
    if (null != m) 
     filler(m, value, dimensions); 
} 

static <T>void filler(Object[] m, T value, int toGo) { 
    if (--toGo <= 0) 
     java.util.Arrays.fill(m, value); 
    else 
     for (Object[] subArray : (Object[][])m) 
      if (null != subArray) 
       filler(subArray, value, toGo); 
} 
0
public static Object[] fillArray(Object[] arr,Object item){ 
    Arrays.fill(arr, item); 
    return arr; 
} 
Character[][] maze = new Character[10][10]; 
    fillArray(maze, fillArray(maze[0], '?')); 

    for(int i = 0;i<10;i++){ 
     System.out.println(); 
     for(int j = 0;j<10;j++){ 
      System.out.print(maze[i][j]); 
     } 
    } 

espero que esto vaya bien

0

uso de Java 8, se puede declarar e inicializar una matriz de dos dimensiones sin necesidad de utilizar un (explícita) De bucle como sigue:

int x = 20; // first dimension 
int y = 4; // second dimension 

double[][] a = IntStream.range(0, x) 
         .mapToObj(i -> new double[y]) 
         .toArray(i -> new double[x][]); 

Esto inicializar las matrices con los valores predeterminados (0.0 en el caso de double).

En caso de que quiera definir explícitamente el valor de relleno a utilizar, puede añadir en una DoubleStream:

int x = 20; // first dimension 
int y = 4; // second dimension 
double v = 5.0; // fill value 

double[][] a = IntStream 
     .range(0, x) 
     .mapToObj(i -> DoubleStream.generate(() -> v).limit(y).toArray()) 
     .toArray(i -> new double[x][]); 
Cuestiones relacionadas