Можно ли динамически построить многомерный массив в Java?

Boost, вероятно, лучший выбор, однако, если вы хотите что-то более автономное, и если оно предназначено для использования с Windows (что представляется возможным, учитывая, что они являются людьми, которые, как минимум, имеют Python), вы можете используйте py2exe , чтобы создать DLL с точками входа, подходящими для COM-объектов. Затем вы можете взаимодействовать с библиотекой через COM. (Очевидно, это совсем не полезно как кросс-платформенное решение).

24
задан Jordan 23 June 2010 в 19:12
поделиться

6 ответов

Это действительно можно сделать в java. (Я немного удивлен, должен сказать.)

Отказ от ответственности; я никогда не хочу видеть этот код где-либо еще, кроме как в качестве ответа на этот вопрос. Я настоятельно рекомендую вам использовать Listы.

import java.lang.reflect.Array;
import java.util.*;

public class Test {

    public static int[] tail(int[] arr) {
        return Arrays.copyOfRange(arr, 1, arr.length);
    }

    public static void setValue(Object array, String value, int... indecies) {
        if (indecies.length == 1)
            ((String[]) array)[indecies[0]] = value;
        else
            setValue(Array.get(array, indecies[0]), value, tail(indecies));
    }

    public static void fillWithSomeValues(Object array, String v, int... sizes) {
        for (int i = 0; i < sizes[0]; i++)
            if (sizes.length == 1)
                ((String[]) array)[i] = v + i;
            else
                fillWithSomeValues(Array.get(array, i), v + i, tail(sizes));
    }

    public static void main(String[] args) {

        // Randomly choose number of dimensions (1, 2 or 3) at runtime.
        Random r = new Random();
        int dims = 1 + r.nextInt(3);

        // Randomly choose array lengths (1, 2 or 3) at runtime.
        int[] sizes = new int[dims];
        for (int i = 0; i < sizes.length; i++)
            sizes[i] = 1 + r.nextInt(3);

        // Create array
        System.out.println("Creating array with dimensions / sizes: " +
                Arrays.toString(sizes).replaceAll(", ", "]["));
        Object multiDimArray = Array.newInstance(String.class, sizes);

        // Fill with some 
        fillWithSomeValues(multiDimArray, "pos ", sizes);

        System.out.println(Arrays.deepToString((Object[]) multiDimArray));


    }
}

Пример вывода:

Creating array with dimensions / sizes: [2][3][2]
[[[pos 000, pos 001], [pos 010, pos 011], [pos 020, pos 021]],
 [[pos 100, pos 101], [pos 110, pos 111], [pos 120, pos 121]]]
19
ответ дан 29 November 2019 в 00:08
поделиться

Массивы безопасны по типу в java - это применимо к простым массивам и «многомерным» массивам, т. Е. массивы массивов.

Если глубина вложения является переменной во время выполнения, лучшее, что вы можете сделать, это использовать массив, который соответствует известной минимальной глубине вложенности (предположительно 1.) Элементы в этом массиве с then либо будут простыми элементами, либо если требуется дальнейшее вложение, другой массив. Массив Object [] позволит вам сделать это, поскольку сами вложенные массивы также считаются объектами и, таким образом, вписываются в систему типов.

Если вложение полностью регулярное, то вы можете вытеснить эту регулярность и создать соответствующий многомерный массив, используя Array.newInstance (String.class, Dimension1, Dimension2, ...) , Если вложенность является нерегулярно, вам будет лучше использовать вложенные списки, которые допускают «зубчатую» структуру и динамическое изменение размера. У вас может быть зубчатая структура за счет дженериков. Обобщения не могут использоваться, если структура зубчатая, поскольку некоторые элементы могут быть простыми элементами, тогда как другие элементы могут быть дополнительными вложенными списками.

4
ответ дан 29 November 2019 в 00:08
поделиться

Таким образом, вы можете передать несколько измерений в Array.newInstance , но это требует фиксированной длины для каждого измерения. Если все в порядке, вы можете использовать следующее:

// We already know from scanning the input that we need a 2 x 4 array.
// Obviously this array would be created some other way. Probably through
// a List.toArray operation.
final int[] dimensions = new int[2];
dimensions[0] = 2;
dimensions[1] = 4;

// Create the array, giving the dimensions as the second input.
Object array = Array.newInstance(String.class, dimensions);

// At this point, array is a String[2][4].
// It looks like this, when the first dimension is output:
// [[Ljava.lang.String;@3e25a5, [Ljava.lang.String;@19821f]
//
// The second dimensions look like this:
// [null, null, null, null]

Другой вариант - построить их снизу, используя getClass на предыдущем уровне массива в качестве входных данных для следующего уровня. Следующий код запускается и создает массив с зазубринами, как определено узлами:

import java.lang.reflect.Array;

public class DynamicArrayTest
{
    private static class Node
    {
        public java.util.List<Node> children = new java.util.LinkedList<Node>();
        public int length = 0;
    }

    public static void main(String[] args)
    {
        Node node1 = new Node();
        node1.length = 1;

        Node node2 = new Node();
        node2.length = 2;

        Node node3 = new Node();
        node3.length = 3;

        Node node4 = new Node();
        node4.children.add(node1);
        node4.children.add(node2);

        Node node5 = new Node();
        node5.children.add(node3);

        Node node6 = new Node();
        node6.children.add(node4);
        node6.children.add(node5);

        Object array = createArray(String.class, node6);
        outputArray(array); System.out.println();
    }

    private static Object createArray(Class<?> type, Node root)
    {
        if (root.length != 0)
        {
            return Array.newInstance(type, root.length);
        }
        else
        {
            java.util.List<Object> children = new java.util.ArrayList<Object>(root.children.size());
            for(Node child : root.children)
            {
                children.add(createArray(type, child));
            }

            Object array = Array.newInstance(children.get(0).getClass(), children.size());
            for(int i = 0; i < Array.getLength(array); ++i)
            {
                Array.set(array, i, children.get(i));
            }

            return array;
        }
    }

    private static void outputArray(Object array)
    {
        System.out.print("[ ");
        for(int i = 0; i < Array.getLength(array); ++i)
        {
            Object element = Array.get(array, i);
            if (element != null && element.getClass().isArray())
                outputArray(element);
            else
                System.out.print(element);

            System.out.print(", ");
        }
        System.out.print("]");
    }
}
3
ответ дан 29 November 2019 в 00:08
поделиться

В качестве дальнейшего примечания, что, если бы мы попробовали что-то вроде этого:

 Object arr1 = Array.newInstance (Array.class, 2);
Объект arr2 = Array.newInstance (String.class, 4);
Объект arr3 = Array.newInstance (String.class, 4);
Array.set (arr1, 0, arr2);
...

Нет, вы не можете установить такое значение String [] . Вы сталкиваетесь с

Exception in thread "main" java.lang.IllegalArgumentException: array element type mismatch
at java.lang.reflect.Array.set(Native Method)
at Test.main(Test.java:12)
1
ответ дан 29 November 2019 в 00:08
поделиться

Действующий элемент Java № ( Я не помню ): Знайте и используйте библиотеки.

Вы можете использовать List и использовать метод toArray :

List<String[]> twoDimension = new ArrayList<String[]>();

Чтобы преобразовать его в массив, вы должны использовать:

String [][] theArray = twoDimension.toArray( new String[twoDimension.size()][] );

Хитрость в том, что внешний массив объявлен как содержащий String [] (строковые массивы), который, в свою очередь, может быть динамически создан с другим List или, если вы анализируете строки, с помощью String. метод split .

Демо

Сосредоточившись на динамическом создании массива, а не на синтаксическом анализе, вот пример того, как это работает, используется вместе с String.split

// and array which contains N elements of M size
String input = "[[1],[2,3],[4,5,6,7],[8,9,10,11,12,13]]";

// Declare your dynamic array
List<String[]> multiDimArray = new ArrayList<String[]>();

// split where ],[ is found, just ignore the leading [[ and the trailing ]]
String [] parts = input.replaceAll("\\[\\[|\\]\\]","") 
                       .split("\\],\\[");

// now split by comma and add it to the list
for( String s : parts ){
    multiDimArray.add(  s.split(",") ) ;
}

String [][] result = multiDimArray.toArray( new String[multiDimArray.size()][]);

Там. Теперь ваш результат представляет собой двумерный динамически созданный массив, содержащий: [[1], [2, 3], [4, 5, 6, 7], [8, 9, 10, 11]. , 12, 13]] , как и ожидалось.

Вот полная работающая демонстрация , которая также добавляет в микс больше регулярных выражений, чтобы устранить пробелы.

Я позволю вам разобраться с другими сценариями.

0
ответ дан 29 November 2019 в 00:08
поделиться

Итак, если вы не знаете размеров массива, то следующий метод не сработает. Однако, если вы знаете размеры, не используйте отражение. Сделайте следующее:

Вы можете динамически строить двухмерные массивы гораздо проще, чем это.

int x = //some value
int y = //some other value

String[][] arr = new String[x][y];

Это "динамически" создаст двухмерный массив x на y.

1
ответ дан 29 November 2019 в 00:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: