2015-03-13 4 views
0

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

Альтернативный вопрос (для справки): Java Proxy Discovering Bot

В принципе, мне нужно хранить очень большие объемы данных и иметь доступ к нему очень быстро. Это будет работать идеально в неограниченной ситуации памяти:

boolean[][][][] sets = new boolean[256][256][256][256]; 
boolean get(byte[] a) { 
    return sets[a[0]][a[1]][a[2]][a[3]]; 
} 

Однако, это использует около 16 Гб оперативной памяти, которая слишком много для моего приложения. Я полагаю, что если использовать биты вместо booleans (хранится как 4 байта на Java), это сократит использование памяти примерно на 512 МБ. Тем не менее, я не могу представить себе, как правильно обращаться к битам. Например, если вы сопоставили каждый адрес примерно так: position = a * b * c * d, то он сопоставил бы тот же бит, что и d * c * b * a и т. Д.

Я нашел эту тему, охватывающую как конвертировать 2D массивов в 1D-массивы, но я не могу склонить голову вокруг того, как расширить это до 4D-массива. Может кто-нибудь объяснить это? Map a 2D array onto a 1D array C

Раствор для 2D -> 1D массивы:

int array[width * height]; 
int SetElement(int row, int col, int value) 
{ 
    array[width * row + col] = value; 
} 

Я просто не уверен в том, как распространить его на 4D -> 1D

int array[256 * 256 * 256 * 256]; 
int setElement(int a, int b, int c, int d, boolean value) 
{ 
    array[?????????] = value; 
} 
+0

Вы можете использовать класс BitSet в Java. Кроме того, вам не нужно удалять любые, кроме последнего измерения. Таким образом, трехмерный массив битовых наборов, где четвертое измерение булевых потоков рушится в BitSet, должно хорошо работать, я думаю? – flup

+0

@flup Я только что проверил это, трехмерный массив BitSet. Однако для их инициализации требуется более 5 минут. (Продолжается, еще не завершено). Я предпочел бы использовать только один бит, кажется, что это возможно при правильном доступе к битам. – Colby

ответ

1

Для ответа о картографической 4D в 1D, если вы визуализируете, скажем, шахматную доску, вы можете придумать формулу для 2D-1D, думая, что каждая строка имеет width элементов, и я сначала спускаю row количество строк, а затем перехожу к col, затем Я нахожусь в width * row + col. Теперь представьте стопку height количество шахматных досок и выполните одно и то же упражнение, чтобы расширить его до трех размеров. Четыре измерения сложнее, потому что вы не можете их реально визуализировать, но к тому моменту вы можете увидеть шаблон.

В этой программе показана формула для четырех измерений. Я запустил его для очень маленьких номеров для публикации здесь, но вы можете играть с размерами и посмотреть, как это работает.

class Dim 
{ 
    // dimensions 
    static int d1 = 2 ; // "rows" 
    static int d2 = 2; // "cols" 
    static int d3 = 3; // "height" 
    static int d4 = 2; // the fourth dimension! 

    public static void main(String[] args) { 
     for (int i=0; i<d1; i++) { 
      for (int j=0; j<d2; j++) { 
       for (int k=0; k<d3; k++) { 
        for (int m=0; m<d4; m++) { 
         int oneD = fourDtoOneD(i, j, k, m); 
         System.out.printf("(%d, %d, %d, %d) -> %d\n", i, j, k, m, oneD); 
        } 
       } 
      } 
     } 
    } 

    static int fourDtoOneD(int i, int j, int k, int m) { 
     return ((d2*d3*d4) * i) + ((d2*d3) * j) + (d2 * k) + m; 
    } 
} 


$ java Dim 
(0, 0, 0, 0) -> 0 
(0, 0, 0, 1) -> 1 
(0, 0, 1, 0) -> 2 
(0, 0, 1, 1) -> 3 
(0, 0, 2, 0) -> 4 
(0, 0, 2, 1) -> 5 
(0, 1, 0, 0) -> 6 
(0, 1, 0, 1) -> 7 
(0, 1, 1, 0) -> 8 
(0, 1, 1, 1) -> 9 
(0, 1, 2, 0) -> 10 
(0, 1, 2, 1) -> 11 
(1, 0, 0, 0) -> 12 
(1, 0, 0, 1) -> 13 
(1, 0, 1, 0) -> 14 
(1, 0, 1, 1) -> 15 
(1, 0, 2, 0) -> 16 
(1, 0, 2, 1) -> 17 
(1, 1, 0, 0) -> 18 
(1, 1, 0, 1) -> 19 
(1, 1, 1, 0) -> 20 
(1, 1, 1, 1) -> 21 
(1, 1, 2, 0) -> 22 
(1, 1, 2, 1) -> 23 
+0

Спасибо, очень четко написано и объяснено. Если вы также хотите опубликовать этот ответ в формате, отвечая на предыдущий вопрос (чтобы облегчить поиск для будущих пользователей), я связался с этим, я был бы рад также предоставить вам ответ. – Colby

+0

Рад, что это помогло! Я думаю, что это хорошо, если бы код в другом вопросе со ссылкой сюда для получения дополнительной информации, как и вы. Кстати, для вашего случая с IP-адресами другой способ подумать об этом состоит в том, чтобы рассмотреть четыре раздела IP как четыре «цифры» в базе 256, которые вы хотите преобразовать в базу 10. Т.е.: «256^3 (i) + 256^2 (j) + 256^1 (k) + 256^0 (m) '. – jas

+0

Вот одна проблема. 256^4 больше Integer.MAX_VALUE. Это означает, что при попытке доступа к более высокому диапазону ips бит-указатель (fourDtoOneD) фактически переходит в отрицательный. Я уверен, что смогу обойти это, используя массив из 256 бит множеств или что-то в этом роде, но это не кажется очень изящным. Хотя нет истинного элегантного способа сделать это.Однако это работает отлично до тех пор, пока не будет достигнут целочисленный предел. Это больше проблема для моего другого потока, хотя и не для этого. По иронии судьбы, новый BitSet (256 * 256 * 256 * 256) возвращает набор с длиной 0: X – Colby

Смежные вопросы