Вопрос
Почему в Java нет реализации настоящих многомерных массивов? Есть ли веская техническая причина? Что мне здесь не хватает?
Справочная информация
В Java есть многомерные массивы на уровне синтаксиса, которые можно объявить
int[][] arr = new int[10][10];
но похоже, что это действительно не то, чего можно было ожидать. Вместо того, чтобы JVM выделяла непрерывный блок ОЗУ, достаточно большой для хранения 100 целых чисел, он представляет собой массив массивов целых чисел: таким образом, каждый уровень представляет собой непрерывный блок ОЗУ, но в целом это не так. Таким образом, доступ к arr[j] происходит довольно медленно: JVM должна
- найти int[], хранящийся в arr;
- индексировать это, чтобы найти int, хранящийся в arr[j].
Это включает в себя запрос к объекту переходить от одного уровня к другому, что довольно дорого.
Почему Java это делает
На одном уровне нетрудно понять, почему это нельзя оптимизировать для простого поиска с масштабированием и добавлением, даже если все это было размещено в одном фиксированном блоке. Проблема в том, что arr[3] — это отдельная ссылка, и ее можно изменить. Таким образом, хотя массивы имеют фиксированный размер, мы могли бы легко написать
arr[3] = new int[11];
и теперь масштабирование и добавление не работает, потому что этот слой увеличился. Во время выполнения вам нужно будет знать, все ли по-прежнему того же размера, что и раньше. Кроме того, конечно, тогда это будет выделено где-то в другом месте в оперативной памяти (так и должно быть, поскольку оно больше, чем то, что заменяет), поэтому оно даже не в нужном месте для масштабирования и добавления.
Что в этом проблемного
Мне кажется, что это не идеально, и то по двум причинам.
Во-первых, это медленно. Тест, который я провел с этими методами для суммирования содержимого одномерного или многомерного массива, занял почти вдвое больше (714 секунд против 371 секунды) для многомерного случая (int[1000000] и int[100][100][100] соответственно, заполненные случайными значениями int, выполненный 1000000 раз с теплым кэш).
public static long sumSingle(int[] arr) {
long total = 0;
for (int i=0; i