2011-08-19 25 views
36

Come posso riempire un array multidimensionale in Java senza utilizzare un loop? Ho provato:Array con array multidimensionale in Java

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

Questo si traduce in java.lang.ArrayStoreException: java.lang.Double

Grazie in anticipo!

+2

ma perché non utilizzare un ciclo? –

+2

@Caroline: se si sta tentando di inizializzare l'array 2d con 0, non è necessario farlo poiché è già stato inizializzato con 0 quando si assegna l'array e non è possibile inizializzare alcun array senza utilizzare un ciclo. È possibile solo nascondere il loop in una funzione proprio come fa Arrays.fill. – Emil

+1

Hey ragazzi non esagerare ora. Tutto quello che voleva era un metodo in Java API per inizializzare array multidimensionali ad un valore predefinito in un singolo passaggio. Questo è quello che voleva dire senza un ciclo. –

risposta

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

Ciao. Sono solo curioso di sapere perché suggerisci questa soluzione e non un classico 'for'. C'è una motivazione? Grazie! – Maverik

+61

A causa delle seguenti parole nella domanda: "senza utilizzare un ciclo". La mia soluzione è chiaramente ridicola, ma risponde correttamente alla domanda. – trojanfoe

+2

Mi dispiace, ho perso il "senza usare un loop" dall'OP: rimosso il mio down-vote. Forse dovresti aver fatto un'osservazione nella tua risposta che il suggerimento non dovrebbe essere preso troppo sul serio. –

69

Questo perché un double[][] è un array di double[] che non è possibile assegnare ad 0.0 (sarebbe come fare double[] vector = 0.0). In effetti, Java non ha veri array multidimensionali.

Si dà il caso, 0.0 è il valore predefinito per il doppio in Java, quindi la matrice in realtà già essere riempiti con gli zeri quando lo si ottiene da new. Tuttavia, se si desidera riempirlo con, ad esempio, 1.0, è possibile effettuare le seguenti operazioni:

Non credo che l'API fornisca un metodo per risolvere questo problema senza utilizzare un ciclo. È abbastanza semplice comunque farlo con un ciclo for-each.

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

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

Questo è sufficiente anche per 'Arrays.fill (arr, 0d);' o 'Arrays.fill (arr, (double) 0);' –

+2

I get' Eccezione nella discussione "main" java.lang.ArrayStoreException: java.lang.Double' a meno che non esegua il loop delle righe. – aioobe

+0

Perché non provi a capire questa risposta? In java (e C e C++) non ci sono array multidimensionali !!! La tua matrice è un semplice array monodimensionale, in cui ogni "campo" è di nuovo un unico array dimensinoale. La tua chiamata a Arrays.fill() tenta di inserire un _int_ (per avere una doppia scrittura 0.0 e non semplicemente 0) nella "matrice", che non funziona. –

3

come posso riempire un array multidimensionale in Java senza l'utilizzo di un ciclo?

array multidimensionali sono solo array di array e fill(...) non controlla il tipo di matrice e il valore si passa (questa responsabilità è sulla sviluppatore).

Quindi non è possibile riempire ragionevolmente un array multidimensionale senza utilizzare un ciclo.

Essere consapevoli del fatto che, a differenza di linguaggi come C o C++, gli array Java sono oggetti e in array multidimensionali tutti tranne l'ultimo livello contengono riferimenti ad altri oggetti Array. Non ne sono sicuro al 100%, ma molto probabilmente sono distribuiti in memoria, quindi non puoi riempire un blocco contiguo senza un ciclo, come C/C++ ti permetterebbe di fare.

7

L'OP ha chiesto come risolvere questo problema senza un ciclo! Per qualche motivo è di moda in questi giorni per evitare i loop. Perchè è questo? Probabilmente c'è la consapevolezza che usando map, reduce, filter e gli amici, e metodi come each nascondono i loop e riducono il verbage del programma e sono piuttosto interessanti. Lo stesso vale per le pipeline Unix davvero dolci. O codice jQuery. Le cose sembrano grandi senza loop.

Ma Java ha un metodo map? Non proprio, ma potremmo definirne uno con un'interfaccia Function con un metodo eval o exec. Non è troppo difficile e sarebbe un buon esercizio. Potrebbe essere costoso e non utilizzato nella pratica.

Un altro modo per fare questo senza un ciclo consiste nell'utilizzare la ricorsione della coda. Sì, è un po 'stupido e nessuno lo userebbe in pratica, ma mostra, forse, che i loop vanno bene in questo caso.Tuttavia, solo per mostrare "l'ennesimo anello libera esempio" e di divertirsi, ecco:

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)); 
    } 
} 

Non è abbastanza, ma in risposta alla domanda del PO, non ci sono espliciti loop.

+0

+1, non per la soluzione, ma per una risposta davvero buona – Dragon8

+0

Grazie per tutte le vostre soluzioni! Il motivo per cui non voglio usare un ciclo? Stavo cercando una soluzione semplice per generare una matrice n-by-n di zeri come in MATLAB. – Caroline

+0

Ciò potrebbe ancora causare un overflow dello stack, in quanto Java non supporta la ricorsione in coda, quindi i ricorsi sono decisamente> ricorsivi. – mc10

1

Come estensione della risposta, ho trovato questo post ma stavo cercando di riempire un array a 4 dimensioni. L'esempio originale è solo un array bidimensionale, ma la domanda dice "multidimensionale". Non volevo postare una nuova domanda per questo ...

È possibile utilizzare lo stesso metodo, ma è necessario nidificarli in modo da ottenere una matrice monodimensionale.

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

Questa riga fa sì che ogni riga si riferisca allo stesso blocco di memoria, cioè cambiando arr [1] [5] cambierà arr [100] [5]. –

0

non siamo tutti a volte vorrei che ci fosse un
<T>void java.util.Arrays.deepFill(T[]…multiDimensional). I problemi iniziano con
Object threeByThree[][] = new Object[3][3];
threeByThree[1] = null; e
threeByThree[2][1] = new int[]{42}; essere perfettamente legale.
(Se solo Object twoDim[]final[] era legale e ben definito ...)
(Utilizzando uno dei metodi pubblici dal basso mantiene loop dal codice sorgente chiamando.
Se ti ostini a usare nessun cicli a tutti, sostituire il loop e la chiamata a Arrays.fill() (!) utilizzando la ricorsione.)

/** 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]); 
     } 
    } 

spero che questo faccia bene

0

utilizzo di Java 8, è possibile dichiarare e inizializzare un array bidimensionale senza utilizzare un (esplicito) Ciclo come segue:

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][]); 

Ciò inizializzare le matrici con valori di default (0.0 nel caso di double).

Nel caso in cui si desidera definire esplicitamente il valore di riempimento da utilizzare, è possibile aggiungere in un 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][]); 
Problemi correlati