Список <Double>, который использует ОЗУ double []? - PullRequest
20 голосов
/ 21 декабря 2011

Эксперты по Java подчеркивают важность избегания преждевременной оптимизации и вместо этого сосредотачиваются на чистом дизайне ОО.Я пытаюсь согласовать этот принцип в контексте переписывания программы, которая использует большой массив длинных элементов (несколько миллионов).Кажется, что использование ArrayList потребляет примерно в 3 раза больше памяти примитивного массива long, и тратить столько оперативной памяти мне кажется законным беспокойством.

Я основываю это на эксперименте, проведенном с использованием класса 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 List и при этом сохранить небольшой объем памятипримитивного массива?Я думаю, что guava может дать ответ, но просматривая API, мне не очевидно, какой класс использовать вместо ArrayList.

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

Ответы [ 6 ]

16 голосов
/ 21 декабря 2011

Я думаю, что вы ищете в Гуаве: Doubles.asList

11 голосов
/ 21 декабря 2011

Вы можете рассмотреть возможность использования Trove , который обеспечивает поддержку примитивных коллекций, например, TDoubleArrayList класс:

Изменяемый размер, массиврезервный список двойных примитивов.

Редактировать: Это правда, что этот класс не реализует List, но это цена Java, позволяющая избегать коробочных примитивов. Решение Guava является наиболее универсальным, в то время как Trove лучше всего подходит для более экстремальных требований к производительности.

5 голосов
/ 21 декабря 2011

Я думаю, что вы ищете FastUtil's DoubleArrayList - он поддерживается примитивным массивом.

Если ваша коллекция действительно большая (больше 2 ^31 элементов) вы также можете посмотреть на их BigArrays

3 голосов
/ 21 декабря 2011

Напишите свою собственную реализацию ArrayList, которая использует массив примитивов.Скопируйте текущий код ArrayList и замените внутренний объект [] на двойной [].

Должно быть довольно прямое копирование и замена.

РЕДАКТИРОВАТЬ: наибольшая опасность для использования памяти будетбыть "расти".Это ненадолго займет как минимум вдвое больше места, плюс дополнительная комната, которую вы выращиваете.Если вы не можете предварительно изменить размер массива, чтобы избежать этого, вы можете рассмотреть несколько другую реализацию, которая использует несколько массивов по мере роста со временем.Немного больше математики при вставке и индексировании, но не должно быть слишком плохо.

1 голос
/ 21 декабря 2011

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

1 голос
/ 21 декабря 2011

Arrays.asList (T ...) может быть то, что вы ищете. Он возвращает экземпляр List<T>, поддерживаемый переданным ему массивом.

...