Come creare un array di array in Java


115

Ipoteticamente, ho 5 oggetti array di stringhe:

String[] array1 = new String[];
String[] array2 = new String[];
String[] array3 = new String[];
String[] array4 = new String[];
String[] array5 = new String[];

e voglio che un altro oggetto array contenga quei 5 oggetti array di stringhe. Come lo faccio? Posso metterlo in un altro array?


43
Le domande di Noob possono essere serie. In effetti, lo sono spesso. :-)
TJ Crowder

3
Domanda pertinente e risposta non ovvia per chi sa come viene eseguito l'allineamento della memoria. +1
Benj

Risposte:


153

Come questo:

String[][] arrays = { array1, array2, array3, array4, array5 };

o

String[][] arrays = new String[][] { array1, array2, array3, array4, array5 };

(La seconda sintassi può essere utilizzata in assegnazioni diverse da quella nel punto della dichiarazione della variabile, mentre la sintassi più breve funziona solo con le dichiarazioni.)


Potresti spiegare ulteriormente cosa fa la seconda sintassi? Non è abbastanza chiaro per me.
Terence Ponce

4
@Terence: fa la stessa cosa del primo: crea un array di riferimenti ad array di stringhe, inizializzati sui valori array1, array2, array3, array4 e array5 - ognuno dei quali è di per sé un riferimento ad array di stringhe.
Jon Skeet

1
Domanda veloce: come lo farò in fase di esecuzione se non ho idea di quanti oggetti array verranno creati?
Terence Ponce

1
@Terence: puoi fornire un esempio più specifico? Quando si sta specificando i valori iniziali al momento della compilazione, si fa conosce la dimensione. Intendi qualcosa di simile new String[10][]?
Jon Skeet

Sì. Simile alla risposta di Peter.
Terence Ponce

71

provare

String[][] arrays = new String[5][];

1
questo è più flessibile
hetaoblog

Non dovresti definire una dimensione fissa sul tuo array?
Filip

@Filip è fissato a 5. L'impostazione del livello successivo li pre-alloca, ma questo può essere modificato in modo che l'impostazione potrebbe non essere utile.
Peter Lawrey

8
Come inserisco i dati nell'array? Se i suoi dati dinamici?
Prakhar Mohan Srivastava

1
@PrakharMohanSrivastava puoi impostare gli elementi individualmente: arrays[0] = new String[] {"a", "b", "c"}o utilizzare un elenco temporaneo: <pre> <code> List <String []> myList = new ArrayList <> (); myList.add (new String [] {"a", "b", "c"}); myList.add (new String [] {"d", "e", "f"}); myList.toArray (array); </code> </pre>
kntx

26

Sebbene ci siano due ottime risposte che ti dicono come farlo, sento che manca un'altra risposta: nella maggior parte dei casi non dovresti farlo affatto.

Gli array sono ingombranti, nella maggior parte dei casi è meglio utilizzare l' API di raccolta .

Con le raccolte è possibile aggiungere e rimuovere elementi e sono disponibili raccolte specializzate per diverse funzionalità (ricerca basata su indice, ordinamento, unicità, accesso FIFO, concorrenza ecc.).

Sebbene sia ovviamente positivo e importante conoscere gli array e il loro utilizzo, nella maggior parte dei casi l'utilizzo delle raccolte rende le API molto più gestibili (motivo per cui le nuove librerie come Google Guava utilizzano a malapena gli array).

Quindi, per il tuo scenario, preferirei un elenco di elenchi e lo creerei usando Guava:

List<List<String>> listOfLists = Lists.newArrayList();
listOfLists.add(Lists.newArrayList("abc","def","ghi"));
listOfLists.add(Lists.newArrayList("jkl","mno","pqr"));

Un po 'più complicato di String [] [], ma consente più operazioni come la concatenazione dei dati. Tuttavia, la tua soluzione non garantisce la dimensione dei dati, il che può essere un problema.
Benj

1
@Benj se necessario, è sempre possibile scrivere un decoratore di liste che accetti solo un certo numero di articoli.
Sean Patrick Floyd,

Esatto, i decoratori / involucri sono un buon modo per garantire la coerenza. Quindi, il modo in cui parliamo è molto più complesso dei semplici array. Quello che ho fatto è una piccola classe di utilità Array2D <T> che incapsula alcuni metodi di base come exixts (...) ecc. L'ho postato di seguito.
Benj

6

c'è la classe che ho menzionato nel commento che abbiamo fatto con Sean Patrick Floyd: l'ho fatto con un uso particolare che necessita di WeakReference, ma puoi cambiarlo con qualsiasi oggetto con facilità.

Spero che questo possa aiutare qualcuno un giorno :)

import java.lang.ref.WeakReference;
import java.util.LinkedList;
import java.util.NoSuchElementException;
import java.util.Queue;


/**
 *
 * @author leBenj
 */
public class Array2DWeakRefsBuffered<T>
{
    private final WeakReference<T>[][] _array;
    private final Queue<T> _buffer;

    private final int _width;

    private final int _height;

    private final int _bufferSize;

    @SuppressWarnings( "unchecked" )
    public Array2DWeakRefsBuffered( int w , int h , int bufferSize )
    {
        _width = w;
        _height = h;
        _bufferSize = bufferSize;
        _array = new WeakReference[_width][_height];
        _buffer = new LinkedList<T>();
    }

    /**
     * Tests the existence of the encapsulated object
     * /!\ This DOES NOT ensure that the object will be available on next call !
     * @param x
     * @param y
     * @return
     * @throws IndexOutOfBoundsException
     */public boolean exists( int x , int y ) throws IndexOutOfBoundsException
    {
        if( x >= _width || x < 0 )
        {
            throw new IndexOutOfBoundsException( "Index out of bounds (get) : [ x = " + x + "]" );
        }
        if( y >= _height || y < 0 )
        {
            throw new IndexOutOfBoundsException( "Index out of bounds (get) : [ y = " + y + "]" );
        }
        if( _array[x][y] != null )
        {
            T elem = _array[x][y].get();
            if( elem != null )
            {
            return true;
            }
        }
        return false;
    }

    /**
     * Gets the encapsulated object
     * @param x
     * @param y
     * @return
     * @throws IndexOutOfBoundsException
     * @throws NoSuchElementException
     */
    public T get( int x , int y ) throws IndexOutOfBoundsException , NoSuchElementException
    {
        T retour = null;
        if( x >= _width || x < 0 )
        {
            throw new IndexOutOfBoundsException( "Index out of bounds (get) : [ x = " + x + "]" );
        }
        if( y >= _height || y < 0 )
        {
            throw new IndexOutOfBoundsException( "Index out of bounds (get) : [ y = " + y + "]" );
        }
        if( _array[x][y] != null )
        {
            retour = _array[x][y].get();
            if( retour == null )
            {
            throw new NoSuchElementException( "Dereferenced WeakReference element at [ " + x + " ; " + y + "]" );
            }
        }
        else
        {
            throw new NoSuchElementException( "No WeakReference element at [ " + x + " ; " + y + "]" );
        }
        return retour;
    }

    /**
     * Add/replace an object
     * @param o
     * @param x
     * @param y
     * @throws IndexOutOfBoundsException
     */
    public void set( T o , int x , int y ) throws IndexOutOfBoundsException
    {
        if( x >= _width || x < 0 )
        {
            throw new IndexOutOfBoundsException( "Index out of bounds (set) : [ x = " + x + "]" );
        }
        if( y >= _height || y < 0 )
        {
            throw new IndexOutOfBoundsException( "Index out of bounds (set) : [ y = " + y + "]" );
        }
        _array[x][y] = new WeakReference<T>( o );

        // store local "visible" references : avoids deletion, works in FIFO mode
        _buffer.add( o );
        if(_buffer.size() > _bufferSize)
        {
            _buffer.poll();
        }
    }

}

Esempio di come usarlo:

// a 5x5 array, with at most 10 elements "bufferized" -> the last 10 elements will not be taken by GC process
Array2DWeakRefsBuffered<Image> myArray = new Array2DWeakRefsBuffered<Image>(5,5,10);
Image img = myArray.set(anImage,0,0);
if(myArray.exists(3,3))
{
    System.out.println("Image at 3,3 is still in memory");
}

4
+1 per il tuo impegno, ma: invece di inizializzare i tuoi campi int a -1 e riassegnarli nel Constructor, dovresti renderli definitivi e assegnarli solo nel Constructor.
Sean Patrick Floyd

1
@Sean: ho modificato il codice (ne ho postato uno nuovo con "no-GC buffer", incluso il tuo saggio commento.
Benj
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.