Список <Double>, который использует RAM double []?
Эксперты Java подчеркивают важность предотвращения преждевременной оптимизации и вместо этого фокусируются на чистом дизайне OO. Я пытаюсь примирить этот принцип в контексте перезаписи программы, которая использует большой массив длинных элементов (несколько миллионов). Похоже, что использование ArrayList будет потреблять около 3x памяти примитивного массива longs и тратить столько RAM, как на законную озабоченность.
Я основываю это на эксперименте, который я использовал, используя класс MemoryTestBench описанный здесь. Мой тест и вывод следующие:
package memory;
import java.util.ArrayList;
import java.util.List;
public class ArrayListExperiment {
public static void main(String[] args) {
ObjectFactory arrayList = new ObjectFactory() {
public Object makeObject() {
List<Long> temp = new ArrayList<Long>(1000);
for (long i=0; i<1000; i++)
temp.add(i);
return temp;
}
};
ObjectFactory primitiveArray = new ObjectFactory() {
public Object makeObject() {
long[] temp = new long[1000];
for (int i=0; i<1000; i++)
temp[i] = i;
return temp;
}
};
MemoryTestBench memoryTester = new MemoryTestBench();
memoryTester.showMemoryUsage(primitiveArray);
memoryTester.showMemoryUsage(arrayList);
}
}
и вывод:
memory.ArrayListExperiment$2 produced [J which took 8016 bytes
memory.ArrayListExperiment$1 produced java.util.ArrayList which took 24968 bytes
Мой вопрос: как я могу извлечь выгоду из списка OO и все еще сохранить небольшой объем памяти примитивного массива? Я думаю, что guava может предоставить ответ, но, просматривая API, мне не кажется, какой класс использовать вместо ArrayList.
Спасибо за любые предложения.
Ответы
Ответ 1
Вы можете использовать Trove, который обеспечивает поддержку примитивных коллекций, например TDoubleArrayList
класс:
Изменчивый, содержащий массив массив двойных примитивов.
Изменить:. Верно, что этот класс не реализует List
, а эту цену Java избегает примитивов в штучной упаковке. Решение Guava является самым универсальным, в то время как Trove лучше подходит для более экстремальных требований к производительности.
Ответ 2
Я думаю, что вы ищете в Гуаве Doubles.asList
Ответ 3
Я думаю, что вы ищете FastUtil DoubleArrayList
- он поддерживается примитивным массивом.
Если ваша коллекция ДЕЙСТВИТЕЛЬНО большая (более 2 ^ 31 элементов), вы также можете посмотреть их BigArrays
Ответ 4
Напишите свою собственную реализацию ArrayList, которая использует массив примитивов. Скопируйте текущий код ArrayList и замените внутренний объект [] двойным [].
Должна быть красивая прямая копия и заменить ее.
EDIT: Самая большая опасность для потребления памяти будет "расти". Он вкратце займет как минимум в два раза больше места, плюс дополнительная комната, в которой вы растете. Если вы не можете предварительно задать размер массива, чтобы избежать этого, вы можете рассмотреть несколько другую реализацию, которая использует несколько массивов, поскольку она растет с течением времени. Немного больше математики при вставке и индексировании, но не должно быть tooooo bad.
Ответ 5
Arrays.asList(T...) может быть тем, что вы ищете. Он возвращает экземпляр List<T>
, поддерживаемый массивом, переданным ему.
Ответ 6
Хороший вопрос - производительность и чистота кода. Я думаю, что у вас есть основания меньше заботиться о чистом дизайне OO и просто сосредоточиться на создании хорошего решения конкретной проблемы работы с большим количеством длин. Если вы это сделаете, сохранение ориентированного на производительность кода в одном классе/пакете минимизирует его влияние на общий дизайн. Предположительно, управление большим списком длин - лишь небольшая часть большего приложения...