Como fazer um array de arrays em Java

115

Hipoteticamente, tenho 5 objetos de array de string:

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

e eu quero outro objeto de matriz para conter esses objetos de matriz de 5 strings. Como eu faço isso? Posso colocá-lo em outra matriz?

Terence Ponce
fonte
43
As perguntas do Noob podem ser sérias. Na verdade, eles freqüentemente são. :-)
TJ Crowder
3
Pergunta pertinente e resposta não é óbvia para quem sabe como é feito o alinhamento da memória. +1
Benj

Respostas:

153

Como isso:

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

ou

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

(A última sintaxe pode ser usada em atribuições diferentes do ponto da declaração da variável, enquanto a sintaxe mais curta funciona apenas com declarações.)

Jon Skeet
fonte
Você poderia explicar melhor o que a segunda sintaxe faz? Não está claro para mim.
Terence Ponce
4
@Terence: faz o mesmo que o primeiro: cria um array de referências de array de string, inicializado com os valores array1, array2, array3, array4 e array5 - cada um dos quais é em si uma referência de array de string.
Jon Skeet
1
Pergunta rápida: como farei isso em tempo de execução se não tenho ideia de quantos objetos de array serão criados?
Terence Ponce
1
@Terence: Você pode dar um exemplo mais específico? Quando você está especificando os valores iniciais em tempo de compilação, você não sabe o tamanho. Você quer dizer algo como new String[10][]?
Jon Skeet
Sim. Semelhante à resposta de Peter.
Terence Ponce
71

experimentar

String[][] arrays = new String[5][];
Peter Lawrey
fonte
1
este é mais
flexível
Você não deveria definir um tamanho fixo em seu array?
Filip
@Filip é fixado em 5. Definir o próximo nível pré-aloca-os, mas isso pode ser alterado, portanto, definir pode não ser útil.
Peter Lawrey
8
Como faço para inserir dados no array? Se seus dados dinâmicos?
Prakhar Mohan Srivastava
1
@PrakharMohanSrivastava você pode definir os elementos individualmente: arrays[0] = new String[] {"a", "b", "c"} ou usar uma Lista temporária: <pre> <code> List <String []> myList = new ArrayList <> (); myList.add (new String [] {"a", "b", "c"}); myList.add (new String [] {"d", "e", "f"}); myList.toArray (arrays); </code> </pre>
kntx
26

Embora existam duas respostas excelentes explicando como fazer isso, sinto que falta outra resposta: na maioria dos casos, você não deve fazer nada.

As matrizes são complicadas; na maioria dos casos, é melhor usar a API de coleta .

Com Coleções, você pode adicionar e remover elementos e há Coleções especializadas para diferentes funcionalidades (pesquisa baseada em índice, classificação, exclusividade, acesso FIFO, simultaneidade etc.).

Embora seja bom e importante saber sobre Arrays e seu uso, na maioria dos casos, o uso de Coleções torna as APIs muito mais gerenciáveis ​​(é por isso que novas bibliotecas como o Google Guava dificilmente usam Arrays).

Então, para o seu cenário, eu preferiria uma lista de listas, e eu a criaria usando Goiaba:

List<List<String>> listOfLists = Lists.newArrayList();
listOfLists.add(Lists.newArrayList("abc","def","ghi"));
listOfLists.add(Lists.newArrayList("jkl","mno","pqr"));
Sean Patrick Floyd
fonte
Um pouco mais complicado do que String [] [], mas permite mais operações, como concatenar dados. No entanto, sua solução não garante o tamanho dos dados, o que pode ser um problema.
Benj
1
@Benj se necessário, sempre é possível escrever um decorador de lista que aceita apenas um determinado número de itens.
Sean Patrick Floyd
Exatos, decoradores / invólucros são uma boa maneira de garantir a coerência. Portanto, a maneira como estamos falando é muito mais complexa do que simples arrays. O que fiz é uma pequena classe de utilitário Array2D <T> que encapsula alguns métodos básicos como exixts (...) etc. Postei isso abaixo.
Benj
6

existe a classe que mencionei no comentário que fizemos com Sean Patrick Floyd: Eu fiz isso com um uso peculiar que precisa de WeakReference, mas você pode alterá-lo por qualquer objeto com facilidade.

Espero que isso possa ajudar alguém algum dia :)

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

}

Exemplo de como usar:

// 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
fonte
4
+1 pelo seu esforço, mas: em vez de inicializar seus campos int para -1 e reatribuí-los no Construtor, você deve torná-los finais e atribuí-los apenas no Construtor.
Sean Patrick Floyd
1
@Sean: Eu modifiquei o código (postei um novo com "no-GC buffer", incluindo seu sábio comentário.
Benj