62
задан 19 March 2016 в 20:58

4 ответа

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;
}

, Чтобы предоставить это себе, каждый объект хеширует уникальное, генерирует хэш-код, который хранится в его Объектном заголовке.

Вы видите от [1 110] http://ideone.com/oGbDJ0 , что каждый вложенный массив является объектом сам по себе.

int[][] array = new int[20][2];
for (int[] arr : array) {
    System.out.println(arr);
}

печать внутреннее представление int[], который является [I сопровождается @ сопровождаемый хэш-кодом () сохраненный в заголовке. Это не, как некоторые полагают, адрес объекта. Адрес не может использоваться в качестве хэш-кода, поскольку объект может быть перемещен в любое время GC (если у Вас нет JVM, которая никогда не перемещает объекты)

[I@106d69c
[I@52e922
[I@25154f
[I@10dea4e
[I@647e05
[I@1909752
[I@1f96302
[I@14eac69
[I@a57993
[I@1b84c92
[I@1c7c054
[I@12204a1
[I@a298b7
[I@14991ad
[I@d93b30
[I@16d3586
[I@154617c
[I@a14482
[I@140e19d
[I@17327b6

, Вы видите, сколько памяти используется, если Вы выключаете TLAB с -XX:-UseTLAB https://печать github.com/peter-lawrey/Performance-Examples/blob/master/src/main/java/vanilla/java/memory/ArrayAllocationMain.java [11 17]

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
53
ответ дан 31 October 2019 в 14:19

Интересный вопрос, я выполнил простую программу

int N = 100000000;
long start = System.currentTimeMillis();
int[][] a = new int[2][N];
System.out.println(System.currentTimeMillis() - start + " ms");

, Которая привела к 160 ms. Затем я выполнил другой вариант

int N = 100000000;
long start = System.currentTimeMillis();
int[][] a = new int[N][2];
System.out.println(System.currentTimeMillis() - start + " ms");

, Который привел к 30897 ms. Таким образом, действительно первая опция кажется очень лучше.

23
ответ дан 31 October 2019 в 14:19
 int[2][veryLargeNumber] 

создает два массива с verlarnumber объектов
, в то время как

 int[veryLargeNumber][2] 

создает verylargenumber массивов, имеющих два объекта.

Примечание: создание массива имеет издержки. так предпочел первый

11
ответ дан 31 October 2019 в 14:19

Короче говоря, int[2][veryLargeNumber] лучший подход.

тот, предложенный Peter (int[] array = new int[2 * veryLargeNumber];), еще лучше, или если память является Вашей проблемой, то можно использовать longs вместо целых чисел (long[] array = new long[veryLargeNumber];), и побитовые операторы, или еще лучше, используют кэширование, когда это возможно.

Остерегаются! Представление [I@106d69c в большинстве дистрибутивов JDK/JRE (& Sun; Oracle), дан System.identityHashCode(), и это не , гарантировал , чтобы быть уникальным на каждый объект. Таким образом, Вы не можете полагаться System.out.println(array); для проверки уникальности объекта массива.

1
ответ дан 31 October 2019 в 14:19

Другие вопросы по тегам:

Похожие вопросы: