Ответ 1
Java фактически реализует только одномерные массивы. Он имеет многомерные типы, однако двумерные массивы фактически реализуются как массив массивов. Каждый массив имеет накладные расходы около 16 байт. Вам лучше с int[2][x]
минимизировать накладные расходы.
Вы можете полностью избежать этой проблемы, используя вспомогательные методы.
final int[] array = new int[2 * veryLargeNumber];
public int get(int x, int y) {
return array[idx(x, y)];
}
public void set(int x, int y, int val) {
array[idx(x, y)] = val;
}
private int idx(int x, int y) {
return x * 2 + y; // or x * veryLargeNumber + y;
}
Чтобы обеспечить это для себя, каждый объект hash уникален, генерирует hashCode, который хранится в его заголовке Object.
Вы можете видеть из http://ideone.com/oGbDJ0, что каждый вложенный массив является само по себе.
int[][] array = new int[20][2];
for (int[] arr : array) {
System.out.println(arr);
}
печатает внутреннее представление int[]
, которое [I
, за которым следует @
, за которым следует hashCode(), хранящийся в заголовке. Это не так, как считают некоторые, адрес объекта. Адрес не может использоваться как hashCode, поскольку объект может быть перемещен в любое время GC (если у вас нет JVM, который никогда не перемещает объекты)
[[email protected]
[[email protected]
[[email protected]
[[email protected]
[[email protected]
[[email protected]
[[email protected]
[[email protected]
[[email protected]
[[email protected]
[[email protected]
[[email protected]
[[email protected]
[[email protected]
[[email protected]
[[email protected]
[[email protected]
[[email protected]
[[email protected]
[[email protected]
Вы можете видеть, сколько памяти используется, если вы отключите TLAB с помощью -XX:-UseTLAB
https://github.com/peter-lawrey/Performance-Examples/blob/master/src/main/java/vanilla/java/memory/ArrayAllocationMain.java
public static void main(String[] args) {
long used1 = memoryUsed();
int[][] array = new int[200][2];
long used2 = memoryUsed();
int[][] array2 = new int[2][200];
long used3 = memoryUsed();
if (used1 == used2) {
System.err.println("You need to turn off the TLAB with -XX:-UseTLAB");
} else {
System.out.printf("Space used by int[200][2] is " + (used2 - used1) + " bytes%n");
System.out.printf("Space used by int[2][200] is " + (used3 - used2) + " bytes%n");
}
}
public static long memoryUsed() {
Runtime rt = Runtime.getRuntime();
return rt.totalMemory() - rt.freeMemory();
}
печатает
Space used by int[200][2] is 5720 bytes
Space used by int[2][200] is 1656 bytes