Подтвердить что ты не робот

Список <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.

Спасибо за любые предложения.

4b9b3361

Ответ 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 и просто сосредоточиться на создании хорошего решения конкретной проблемы работы с большим количеством длин. Если вы это сделаете, сохранение ориентированного на производительность кода в одном классе/пакете минимизирует его влияние на общий дизайн. Предположительно, управление большим списком длин - лишь небольшая часть большего приложения...