Java: универсальные статические многомерные массивы - PullRequest
1 голос
/ 28 октября 2011

Если это возможно, как я могу создать статический многомерный массив в Java с различными примитивными типами данных на измерение?

Под статическим я подразумеваю примитивный массив, который не является динамическим, какArrayList будет.

Ответы [ 5 ]

2 голосов
/ 28 октября 2011

Вы не можете.

Многомерный массив по определению является массивом массивов массивов ... чего-либо. Таким образом, ни одно из этих измерений, кроме последнего, не может быть ничем иным, кроме массива. По крайней мере, по традиционному определению. Но если вы имеете в виду что-то еще под «многомерным массивом», вам нужно будет сказать нам, что это такое.

Что касается "статического", это слово сильно перегружено в программировании, и каждый язык, который я могу придумать, использует его для обозначения чего-то немного другого. В Java static означает «принадлежит классу, а не экземплярам этого класса». Опять же, если вы подразумеваете что-то еще под «статичным», вам нужно будет сказать нам, что это такое.

Редактировать : В первоначальном сообщении вопрос не включал слово "примитив". Это немного меняет это. Действительно, я согласен, что было бы неплохо с точки зрения удобства, если бы Java позволяла индексировать массивы с помощью char или даже enum, а не просто int. Но это не так.

1 голос
/ 28 октября 2011

Размеры в массиве всегда от типа int.Подумайте об этом!

int a = 4;
int b = 5;

Shoe shoe = new Shoe (Color.RED, 42, "Leather");
Hat hat = new Hat (17, Color.Black);

Foo foo = foos[a][b];
Zilch pop = bars[shoe][hat]; // no go

Если у вас есть многомерный массив Foos, первое измерение - это Foo, второе - массив Foos, третье - массив массива Foo.Единственный тип переменной - тот, что внизу.

Редактировать после обновления вопроса:

Массивы не называются статическими или примитивными.Их размер фиксируется при инициализации, и они имеют общее с примитивами в том, что они являются buildin, что в некоторых случаях представляет особую опасность.Они - в отличие от так называемых примитивных типов, которые не являются такими примитивными (у них есть, например, операторы, исключительно для своих собственных, например * / -), но в то же время они являются объектами, но не объявлены в библиотеке.

Назовите их build in-types.

Используя трюк Беш Гурунга:

Object[] arr = {new Integer[]{}, new String[]{}, new Double[]{}}; 

требует проблем, и он не состоит из разных типов данных для измерения.Давайте начнем с измерений:

// One-dimensional object:
JPanel [] panels = new JPanel [3]; 
// Two-dimensional object:
JPanel [][] panels = new JPanel [3][10]; 

У вас есть JPanels на нижнем уровне и массив JPanel на следующем измерении.Вы можете добавить больше измерения, и всегда получите дополнительный (Array of ...) обернутый вокруг.

Вы не можете смешивать различные типы данных в массиве, такие как int и char, или JPanel и JFrame, или int и JButton.Только если вы абстрагируетесь от разницы и используете JComponent для JPanel и JFrame в качестве общего родителя, но это не будет работать для встроенных типов int, char, boolean и т. Д., Поскольку они не являются объектами.

Но разве вы не можете использовать автобокс и использовать Integer вместо int, Character вместо char, а затем использовать Object в качестве общего родительского класса?Да, вы могли бы, но тогда вы больше не используете примитивы и просите неприятностей.

Дэн говорит о другом - об использовании разных типов для индексации в многомерном массиве:

byte  b = 120;
short s = 1000;
String o [][] = new String[b][s];
b = 7;
s = 9;  
o[b][s] = "foobar";
String foo = o[b][s];

Нет проблем с использованием байтов или шортов, но вы не можете ограничитьразмер массива, объявив его как байтовый или короткий.В большинстве случаев границы встроенного целочисленного типа не будут соответствовать типу данных (например, 365 дней в году), особенно, поскольку все типы могут становиться отрицательными, поэтому проверка границ необходима, хотя и не может быть ограничена для компиляциивремя.

Но теперь возникли проблемы:
Мы могли бы объявить массив двумерным с самого начала:

Object[][] ar2 = {
    new Integer [] {4, 5, 6}, 
    new String [] {"me", "and", "you"}, 
    new Character [] {'x', 'y', 'z'}};

Это прекрасно работает и делает внутренние массивы доступными сразу, без приведения,Но только для компилятора известно, что элементы являются массивами объектов - базовый тип абстрагируется, и поэтому мы можем написать:

ar2[1][1] = 17; // expected: String
ar2[2][0] = "double you"; // expected: Char

Это скомпилируется без ошибок, но вы стреляете в себяпешком и получите исключение Runtime бесплатно.

Вот источник в целом:

public class ArrOfMixedArr
{
    public static void main (String args[])
    {
        Object[] arr = {
            new Integer [] {1, 2, 3}, 
            new String [] {"you", "and", "me"}, 
            new Character [] {'a', 'b', 'c'}};
        show (arr);

        byte b = 7;
        short s = 9;
        String o [][] = new String[200][1000];
        o[b][s] = "foobar";
        String foo = o[b][s];

        Object[][] ar2 = {
            new Integer [] {4, 5, 6}, 
            new String [] {"me", "and", "you"}, 
            new Character [] {'x', 'y', 'z'}};
        show (ar2);

        // exeptions:
        ar2[1][1] = 17; // expected: String
        ar2[2][0] = "double you"; // expected: Char
    }

    public static void show (Object[] arr)
    {
        for (Object o : arr) 
        {
            if (o instanceof Object[])
                show ((Object[]) o);
            else 
                System.out.print (o.toString () + "\t");
        }
        System.out.println ();
    }
}

Теперь, каково решение?Если ваши массивы базовых типов (int, byte, char, String, JPanel, ...) имеют одинаковую длину, то у вас есть что-то вроде скрытого объекта, строки базы данных.Вместо этого используйте класс:

class Shoe {
    byte size;
    String manufactor;
    java.math.BigDecimal price;
    java.awt.Color color;
}

Shoe [] shoes = new Shoe [7];

Если у вас нет разных типов одинакового размера, они могут быть не связаны и не должны помещаться в общий контейнер.

1 голос
/ 28 октября 2011

После некоторого тестирования у меня есть простое решение:

Object [][] array = new Object [10][2];
array[0][0] = 2;
array[0][1] = false;
0 голосов
/ 14 мая 2015

Вы можете получить эффект, используя массив объектов:

final static Object tryit[][] = {
        {'a',4},
        {'b',7},
        {'c',8},
};
@Test
public void accessArray( ) {
    for (int i = 0; i < tryit.length ; i++) {
        char letter = (Character)tryit[i][0];
        int value = (Integer)tryit[i][1];
        System.out.println(letter + " has value " + value);
    }
}

"@Test" - это JUnit аннотация.

Обратите внимание, что этот подход будет подвергаться исключениям NullPointer и ClassCast во время выполнения, если в массив введены неправильные данные.

0 голосов
/ 28 октября 2011

Ну, вы могли бы определить массив массива из ... массива объектов (вложенных в столько уровней, сколько измерений) и на нижнем уровне заполнить каждый массив различным типоми затем, когда вам нужно извлечь значение, приведите его к соответствующему типу.Слишком много работы ради чего стоит, правда.Ява не годится для такого рода вещей, поскольку является статически типизированным языком.

Может быть, вам следует пересмотреть, зачем вам такая структура данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...