Як зробити масив масивів у 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
Питання Noob можуть бути серйозними. Насправді вони часто є. :-)
TJ Crowder

3
Відповідне питання та відповідь не очевидні для того, хто знає, як здійснюється вирівнювання пам'яті. +1
Бендж

Відповіді:


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
цей є більш
гнучким

Ви не повинні визначити фіксований розмір у своєму масиві?
Філіп

@Filip встановлено на 5. Якщо встановити наступний рівень, попередньо розподіляйте їх, але це можна змінити, щоб встановити його, можливо, не буде корисно.
Пітер Лодрі

8
Як вставити дані в масив? Якщо його динамічні дані?
Прахар Мохан Срівастава

1
@PrakharMohanSrivastava ви можете встановити елементи окремо: arrays[0] = new String[] {"a", "b", "c"}або скористатися тимчасовим списком: <pre> <code> Список <String []> myList = new ArrayList <> (); myList.add (новий рядок [] {"a", "b", "c"}); myList.add (новий рядок [] {"d", "e", "f"}); myList.toArray (масиви); </code> </pre>
kntx

26

Хоча є два чудових відповіді, які розповідають про те, як це зробити, я відчуваю, що ще одна відповідь відсутня: У більшості випадків ви взагалі не повинні цього робити.

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

За допомогою колекцій ви можете додавати та видаляти елементи, а також існують спеціалізовані колекції для різних функціональних можливостей (пошук на основі індексу, сортування, унікальність, 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 [] [], але дозволяє більше операцій, таких як об'єднання даних. Однак ваше рішення не забезпечує розмір даних, що може бути проблемою.
Бендж

1
@Benj, якщо необхідно, завжди можна написати декоратор списку, який приймає лише певну кількість елементів.
Шон Патрік Флойд

Точні, декоратори / обгортки - хороший спосіб забезпечити узгодженість. Таким чином, спосіб, про який ми говоримо, набагато складніший, ніж прості масиви. Що я зробив, це невеликий утилітний клас Array2D <T>, який інкапсулює деякі основні методи, такі як exixts (...) тощо. Я розмістив це нижче.
Бендж

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

4
+1 для ваших зусиль, але: замість того, щоб ініціалізувати ваші поля int до -1 та перепризначити їх у конструкторі, ви повинні зробити їх остаточними та призначити їх лише у конструкторі.
Шон Патрік Флойд

1
@Sean: Я змінив код (опублікував новий з "буфером без GC", включаючи ваш мудрий коментар.
Benj
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.