2015-06-14 3 views
1

Мне нужно преобразовать карту в 2D-массив, поэтому я написал этот фрагмент кода, но он ест много памяти, и я не могу понять, почему.Преобразование коллекции в массив без дополнительной памяти

private DataItem[][] convertDataToArrays(boolean[] filter, 
             Map<Integer, List<T>> dataSet)       
     double[] data = new double[sizeOfNewVector]; 
     DataItem[][] reducedData = new DataItem[dataSet.size()][]; 
     for (int i = dataSet.size() - 1; i >= 0; i--) { 
      reducedData[i] = new DataItem[dataSet.get(i).size()]; 
      for (int j = reducedData[i].length - 1; j >= 0; j--) { 
       reducedData[i][(reducedData[i].length - 1) - j] = new DataItem(data); 
       dataSet.get(i).remove(j); 
      } 
      dataSet.remove(i); 
     } 
     return reducedData; 

здесь DataItem класс:

public class DataItem { 

    public double[] data; 

    public DataItem(double[] data) { 
     this.data = new double[data.length]; 
     System.arraycopy(data, 0, this.data, 0, data.length); 
    } 
} 

Какой алгоритм должен сделать:

  1. взять последний элемент из списка
  2. скопировать его.
  3. удаления элемента из списка
  4. магазин не копировать в новый 2D массив
  5. повторить, пока список пуст

это должно пойти на все списки в карте.

Проблема заключается в том, что шаг 3. просто оставить элемент и не сжать массив, поэтому, когда я вставляю огромный массив данных в методе новообращенного, у меня java.lang.OutOfMemoryError: GC предел накладных расходов превысил

Мне нужно сделать это без дополнительной памяти. Кто-нибудь может мне помочь?

EDIT:

Я использую ArrayList и HashMap.

+1

Почему вам нужно копировать объекты DataItem, если вы удаляете оригиналы? Просто скопируйте ссылки в результирующий массив.Просьба указать, насколько велика 'dataSet' в вашем случае (примерно, сколько у вас объектов DataItem). –

+0

Я удалил один внутренний цикл, где я изменяю «данные». Это может быть более короткий вектор. Это не важно для моего вопроса, и я не хотел путать людей здесь. –

+0

Вам всегда понадобится * дополнительная * дополнительная память для процесса. Я не знаю, какие коллекции вы используете для типов «Карта» и «Список», но * каждый * будет уменьшать размер в какой-то момент (хотя и не сразу). 'HashMap' и' ArrayList', вероятно, будут занимать больше времени, чем, скажем, 'TreeMap' и' LinkedList', но в изменении 'LinkedList' имеет значительные накладные расходы памяти для начала. Я думаю, ваша проблема в том, что вы работаете очень, очень близко к пределу памяти. Если вы не можете заплатить за это накладные расходы и уйти от него каким-то образом, он укусит вас где-то в другом месте. – mastov

ответ

1

Ваша теория полностью возможна. Для сокращения размера внутреннего массива, используемого для хранения ссылок, требуется некоторое время ArrayList. Вы можете избежать этого эффекта, используя другую реализацию , такую ​​как LinkedList, которая не показывает этого поведения, но у них также есть значительные накладные расходы памяти, которые могут съесть пространство, которое вы сохранили.

Учитывая, что, учитывая вашу структуру данных, я считаю маловероятным, что только накладные расходы некоторых дополнительных ссылок в ArrayList подталкивают вашу память к вершине. Я нахожу гораздо более вероятным создание копий всех ваших, по-видимому, относительно больших (судя по массиву внутри) объектов типа DataItem. Если кто-то еще есть ссылки на оригинальные DataItem объектов, ваш призыв к remove удалит их ссылки из списка, но сами объекты остаться в живых до тех пор, все ссылки на них не будут удалены.

Я бы рекомендовал проверить ваш объем памяти с меньшим примером, который действительно работает, используя что-то вроде MAT tool. Посмотрите, сколько объектов типа DataItem у вас есть до и после конверсия. Если бы они увеличились, моя теория была правильной, и вам следует избегать этой проблемы, не копируя объекты , а только их ссылается (если возможно), или избавляясь от дополнительных ссылок на старые объекты. Если моя теория была неправильной, проверьте, какая часть памяти больше всего подходит для идентификации преступника.