So erstellen Sie ein Array von Arrays in Java

115

Hypothetisch habe ich 5 String-Array-Objekte:

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

und ich möchte, dass ein anderes Array-Objekt diese 5 String-Array-Objekte enthält. Wie mache ich es? Kann ich es in ein anderes Array einfügen?

Terence Ponce
quelle
43
Noob-Fragen können ernst sein. In der Tat sind sie häufig. :-)
TJ Crowder
3
Eine relevante Frage und Antwort ist nicht offensichtlich, wer weiß, wie die Speicherausrichtung erfolgt. +1
Benj

Antworten:

153

So was:

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

oder

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

(Die letztere Syntax kann in anderen Zuweisungen als am Punkt der Variablendeklaration verwendet werden, während die kürzere Syntax nur mit Deklarationen funktioniert.)

Jon Skeet
quelle
Können Sie weiter erklären, was die zweite Syntax bewirkt? Es ist mir irgendwie unklar.
Terence Ponce
4
@Terence: Es macht dasselbe wie das erste: Es erstellt ein Array von String-Array-Referenzen, die mit den Werten array1, array2, array3, array4 und array5 initialisiert sind - von denen jeder für sich eine String-Array-Referenz ist.
Jon Skeet
1
Kurze Frage: Wie mache ich das zur Laufzeit, wenn ich keine Ahnung habe, wie viele Array-Objekte erstellt werden?
Terence Ponce
1
@Terence: Können Sie ein genaueres Beispiel geben? Wenn Sie die Anfangswerte zur Compile-Zeit sind die Angabe, Sie haben die Größe kennen. Meinst du so etwas wie new String[10][]?
Jon Skeet
Ja. Ähnlich wie Peters Antwort.
Terence Ponce
71

Versuchen

String[][] arrays = new String[5][];
Peter Lawrey
quelle
1
Dieser ist flexibler
Hetaoblog
Sollten Sie nicht eine feste Größe für Ihr Array definieren?
Filip
@Filip ist fest auf 5 eingestellt. Wenn Sie die nächste Ebene festlegen, werden sie vorab zugewiesen. Dies kann jedoch geändert werden, sodass die Einstellung möglicherweise nicht sinnvoll ist.
Peter Lawrey
8
Wie füge ich Daten in das Array ein? Wenn seine dynamischen Daten?
Prakhar Mohan Srivastava
1
@PrakharMohanSrivastava Sie können die Elemente einzeln festlegen: arrays[0] = new String[] {"a", "b", "c"}oder eine temporäre Liste verwenden: <pre> <code> List <String []> myList = new ArrayList <> (); myList.add (neuer String [] {"a", "b", "c"}); myList.add (neuer String [] {"d", "e", "f"}); myList.toArray (Arrays); </ code> </ pre>
kntx
26

Obwohl es zwei ausgezeichnete Antworten gibt, die Ihnen sagen, wie es geht, fehlt meiner Meinung nach eine andere Antwort: In den meisten Fällen sollten Sie es überhaupt nicht tun.

Arrays sind umständlich. In den meisten Fällen ist es besser, die Collection-API zu verwenden .

Mit Sammlungen können Sie Elemente hinzufügen und entfernen, und es gibt spezielle Sammlungen für verschiedene Funktionen (indexbasierte Suche, Sortierung, Eindeutigkeit, FIFO-Zugriff, Parallelität usw.).

Während es natürlich gut und wichtig ist, über Arrays und deren Verwendung Bescheid zu wissen, macht die Verwendung von Sammlungen APIs in den meisten Fällen viel einfacher zu verwalten (weshalb neue Bibliotheken wie Google Guava Arrays kaum verwenden).

Für Ihr Szenario würde ich eine Listenliste bevorzugen und diese mit Guava erstellen:

List<List<String>> listOfLists = Lists.newArrayList();
listOfLists.add(Lists.newArrayList("abc","def","ghi"));
listOfLists.add(Lists.newArrayList("jkl","mno","pqr"));
Sean Patrick Floyd
quelle
Ein bisschen komplizierter als String [] [], erlaubt aber mehr Operationen wie das Verketten von Daten. Ihre Lösung gewährleistet jedoch nicht die Größe der Daten, was ein Problem sein kann.
Benj
1
@Benj Bei Bedarf ist es immer möglich, einen Listendekorateur zu schreiben, der nur eine bestimmte Anzahl von Elementen akzeptiert.
Sean Patrick Floyd
Genau, Dekorateure / Wrapper sind ein guter Weg, um Kohärenz zu gewährleisten. Daher ist die Art und Weise, wie wir sprechen, weitaus komplexer als einfache Arrays. Was ich getan habe, ist eine kleine Dienstprogrammklasse Array2D <T>, die einige grundlegende Methoden wie Exixte (...) usw. kapselt. Ich habe dies unten gepostet.
Benj
6

Es gibt die Klasse, die ich in dem Kommentar erwähnt habe, den wir mit Sean Patrick Floyd hatten: Ich habe sie mit einer besonderen Verwendung gemacht, die WeakReference benötigt, aber Sie können sie mit Leichtigkeit durch jedes Objekt ändern.

Ich hoffe, das kann eines Tages jemandem helfen :)

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

}

Beispiel für die Verwendung:

// 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");
}
Benj
quelle
4
+1 für Ihre Bemühungen, aber: Anstatt Ihre int-Felder auf -1 zu initialisieren und sie im Konstruktor neu zuzuweisen, sollten Sie sie endgültig machen und sie nur im Konstruktor zuweisen .
Sean Patrick Floyd
1
@ Sean: Ich habe den Code geändert (einen neuen mit "no-GC buffer" gepostet, einschließlich Ihres weisen Kommentars.
Benj