#java #arraylist #multidimensional-array
#java #список массивов #многомерный массив
Вопрос:
Я хотел бы представить матричные данные в подходящей структуре данных на Java. Размеры этой матрицы зависят от пользовательского ввода. Вероятно, одним из способов было бы использовать «волшебную» максимальную константу и использовать простой многомерный массив. Но операции с данными сильно зависят от измерения, и я хотел бы избегать фиксированных массивов, поскольку мне всегда нужно отслеживать используемое и максимальное измерение. Более динамичный подход, конечно, заключается в определении чего-то вроде
private ArrayList<ArrayList<ArrayList<Point>>> arr3d = new ArrayList<ArrayList<ArrayList<Element>>>();
Я думаю, что это неприемлемо некрасиво. Возможно, было бы лучше определить пользовательскую структуру данных, то есть одномерный список массивов (или вектор), а затем каким-то образом обернуть это, т. Е. Сопоставить доступ, указанный как [i, j, k], с некоторым элементом этого единого списка. Возможно ли перезаписать оператор []? Как сделать это эффективно? Есть ли какая-нибудь существующая библиотека или код, на которые я мог бы опереться?
PS: Я думал, что это может быть распространенной проблемой, но, несмотря на все усилия, я не нашел существующего вопроса. Заранее извиняюсь, если я пропустил какой-то ответ.
Комментарии:
1. Я все еще не понимаю, почему не использовать массивы…
2. @m0skit0 Потому что вы должны статически объявить их количество измерений (т. Е.
double[][]
vsdouble[][][]
), и в op говорится, что это должно быть определено во время выполнения. (Я думаю)
Ответ №1:
Почему бы вам не создать свой собственный класс для этого? Он может содержать ваш 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 amp;amp; elements.get(x).size() > y amp;amp; elements.get(x).get(y).size() > z ? elements.get(x).get(y).get(z) : null);
}
И вам нужны методы put, которые при необходимости создают строки (как список массивов).
Ответ №2:
Из вашего вопроса не сразу понятно, что вы подразумеваете под максимальным размером матрицы. Всегда ли он трехмерный или может быть N-мерным на основе ввода пользователя?
Предполагая, что он трехмерный, является ли он регулярным? Является ли каждая матрица [i, j], [i, k] и [j, k] такой же, как и все остальные?
Если это так, вы могли бы предположительно смоделировать структуру как единый плоский список с двумя переменными — одна указывает длину строки на одном уровне матрицы, а другая указывает длину сетки в трехмерной структуре. Целочисленное деление даст вам трехмерное расположение в структуре:
учитывая idx n, длину строки k и базовый размер K:
n/K
дает вам уровень и (n%K)/k
дает вам строку на этом уровне. ((n%K))%k
должен дать вам индекс внутри строки, если я не ошибаюсь.
Оберните это в класс, который заключает в себе эту логику, и вы можете рассматривать его как трехмерную структуру извне.
Ответ №3:
Как насчет ArrayList<Point[]>
? Вы можете даже подумать о реализации AbstractList
для создания собственного списка (даже если вы используете ArrayList
внутренне) и завершить создание Point
массива…