Как сделать массив массивов на Java

115

Гипотетически у меня есть 5 объектов строкового массива:

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

и я хочу, чтобы другой объект массива содержал эти 5 объектов строкового массива. Как мне это сделать? Могу я положить его в другой массив?

Теренс Понсе
источник
43
Вопросы нубов могут быть серьезными. Фактически, они часто бывают такими. :-)
TJ Crowder
3
Уместный вопрос, и ответ не очевиден для тех, кто знает, как выполняется выравнивание памяти. +1
Benj

Ответы:

153

Как это:

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

или

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

(Последний синтаксис может использоваться в назначениях, отличных от места объявления переменной, тогда как более короткий синтаксис работает только с объявлениями.)

Джон Скит
источник
Не могли бы вы объяснить, что делает второй синтаксис? Мне это как-то непонятно.
Теренс Понсе
4
@Terence: он делает то же самое, что и первый: он создает массив ссылок на строковый массив, инициализированных значениями array1, array2, array3, array4 и array5, каждый из которых сам по себе является ссылкой на строковый массив.
Джон Скит,
1
Быстрый вопрос: как мне это сделать во время выполнения, если я не знаю, сколько объектов массива будет создано?
Теренс Понсе,
1
@Terence: Вы можете привести более конкретный пример? Когда вы указываете начальные значения во время компиляции, вы точно знаете размер. Вы имеете в виду что-то вроде new String[10][]?
Джон Скит,
Да. Подобно ответу Питера.
Теренс Понсе,
71

пытаться

String[][] arrays = new String[5][];
Питер Лоури
источник
1
этот более гибкий
hetaoblog
Разве вы не должны определить фиксированный размер вашего массива?
Филип
@Filip фиксируется на 5. Установка следующего уровня заранее выделяет их, но это можно изменить, поэтому установка может быть бесполезной.
Питер Лоури 08
8
Как мне вставить данные в массив? Если его динамические данные?
Пракхар Мохан Шривастава
1
@PrakharMohanSrivastava вы можете установить элементы индивидуально: arrays[0] = new String[] {"a", "b", "c"}или использовать временный список: <pre> <code> List <String []> myList = new ArrayList <> (); myList.add (new String [] {"a", "b", "c"}); myList.add (new String [] {"d", "e", "f"}); myList.toArray (массивы); </code> </pre>
kntx
26

Хотя есть два отличных ответа, рассказывающих вам, как это сделать, я чувствую, что отсутствует другой ответ: в большинстве случаев вам вообще не следует этого делать.

Массивы громоздкие, в большинстве случаев лучше использовать Collection API .

С помощью Коллекций вы можете добавлять и удалять элементы, и существуют специализированные Коллекции для различных функций (поиск на основе индекса, сортировка, уникальность, FIFO-доступ, параллелизм и т. Д.).

Хотя, конечно, хорошо и важно знать о массивах и их использовании, в большинстве случаев использование коллекций делает API-интерфейсы намного более управляемыми (вот почему новые библиотеки, такие как Google Guava, почти не используют массивы).

Итак, для вашего сценария я бы предпочел список списков, и я бы создал его с помощью Guava:

List<List<String>> listOfLists = Lists.newArrayList();
listOfLists.add(Lists.newArrayList("abc","def","ghi"));
listOfLists.add(Lists.newArrayList("jkl","mno","pqr"));
Шон Патрик Флойд
источник
Немного сложнее, чем String [] [], но позволяет выполнять больше операций, таких как объединение данных. Однако ваше решение не гарантирует размер данных, что может быть проблемой.
Benj
1
@Benj, если необходимо, всегда можно написать декоратор List, который принимает только определенное количество элементов.
Шон Патрик Флойд
Точнее, декораторы / обертки - хороший способ обеспечить согласованность. Таким образом, способ, о котором мы говорим, намного сложнее, чем простые массивы. Я сделал небольшой служебный класс Array2D <T>, который инкапсулирует некоторые базовые методы, такие как exixts (...) и т. Д. Я разместил это ниже.
Benj
6

есть класс, который я упомянул в комментарии к Шону Патрику Флойду: я сделал это со специфическим использованием, которое требует WeakReference, но вы можете легко изменить его любым объектом.

Надеюсь, это когда-нибудь поможет кому-то :)

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

}

Пример использования:

// 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
источник
4
+1 за ваши усилия, но: вместо того, чтобы инициализировать ваши поля int до -1 и переназначать их в Конструкторе, вы должны сделать их окончательными и назначить их только в Конструкторе.
Шон Патрик Флойд
1
@Sean: Я изменил код (опубликовал новый с «буфером без
Бендж