Лучший способ "обернуть" ArrayList в Java? - PullRequest
3 голосов
/ 07 ноября 2011

Я бы хотел представить матричные данные в подходящей структуре данных на Java. Размеры этой матрицы зависят от пользовательского ввода. Один из способов, вероятно, состоит в том, чтобы использовать «магическую» max-константу и использовать простой многомерный массив. Но операции с данными сильно зависят от измерения, и я хотел бы избегать фиксированных массивов, поскольку мне всегда нужно было отслеживать используемое и максимальное измерение. Конечно, более динамичный подход состоит в том, чтобы определить что-то вроде

private ArrayList<ArrayList<ArrayList<Point>>> arr3d = new ArrayList<ArrayList<ArrayList<Element>>>();

Я думаю, что это неприемлемо безобразно. Возможно, было бы лучше определить пользовательскую структуру данных, то есть одномерный ArrayList (или Vector), а затем каким-то образом обернуть это, то есть сопоставить доступ, указанный как [i, j, k], с некоторым элементом этого единого списка. Можно ли переписать оператор []? Как это сделать эффективно? Есть какая-нибудь существующая библиотека или код, на который я мог бы опираться?

PS: Я думал, что это может быть распространенной проблемой, но, несмотря на все усилия, я не нашел существующего вопроса. Заранее извиняюсь, если я пропустил какой-либо ответ.

Ответы [ 3 ]

4 голосов
/ 07 ноября 2011

Почему бы вам не создать свой собственный класс, чтобы обернуть это?Он может содержать ваш 3d-список внутри, но вы предоставляете только «удобные» методы для доступа и установки элементов.

И нет, в Java нет возможности перегрузить []

Быстропомощник для этого:

public class Cube<T> {
    private final List<List<List<T>>> elements = new ArrayList<List<List<T>>>();

    public T get(final int x, final int y, final int z) {
        if (elements.size() > x) {
            final List<List<T>> rowx = elements.get(x);
            if (rowx.size() > y) {
                final List<T> rowy = rowx.get(y);
                if (rowy.size() > z) {
                    return rowy.get(z);
                }
            }
        }
        return null;
    }
} 

Вы даже можете сделать это в одну строку, если вы не беспокоитесь о читабельности:

public T get(final int x, final int y, final int z) {
    return (elements.size() > x && elements.get(x).size() > y && elements.get(x).get(y).size() > z ? elements.get(x).get(y).get(z) : null);
}

И вам нужны методы put, которые создают строки (как ArrayList) при необходимости.

2 голосов
/ 07 ноября 2011

Из вашего вопроса не сразу понятно, что вы подразумеваете под максимальным размером матрицы.Это всегда 3-мерное, или оно может быть N-мерным в зависимости от ввода пользователя?

Предполагая, что это 3-мерное, это регулярно?Являются ли все матрицы [i, j], [i, k] и [j, k] такими же, как и все остальные?

Если это так, вы могли бы предположительно смоделировать структуру как один плоский список с двумя переменными- один, указывающий длину строки на одном уровне матрицы, и другой, указывающий длину сетки в 3d-структуре.Целочисленное деление даст вам 3-е местоположение в структуре:

с учетом idx n, длиной строки k и базовым размером K:

n/K дает вам уровень, а (n%K)/k даетВы ряд на этом уровне.((n%K))%k должен дать вам индекс в строке, если я не ошибаюсь.

Оберните это в класс, который заключает в себе эту логику, и вы можете рассматривать его как 3d-структуру извне.

0 голосов
/ 07 ноября 2011

А как насчет ArrayList<Point[]>? Вы даже можете подумать о реализации AbstractList для создания собственного списка (даже если вы используете ArrayList внутри) и обернуть создание массива Point ...

...