Java ArrayList ‹примитивный тип данных› последовательное выделение памяти только для ссылок?

Я хочу выделить массив объектов примитивных типов данных, таких как int, char и т. Д. (Не массив, потому что он будет расти в будущем, может быть не линейно), но должен храниться в последовательных местах памяти в ОЗУ (управляемая куча jvm). Но с тех пор, как я объявил ArrayList для примитивного типа данных, например. ArrayList для int, внутренне jvm сопоставляется с типом объектов ArrayList ‹Integer>.
Теперь проблема в том, что ArrayList содержит последовательные ссылки на объекты, хранящиеся в разных местах в управляемом пространстве памяти jvm. Но моя первоначальная идея заключалась в том, чтобы иметь последовательное хранение реальных объектов данных, а НЕ ТОЛЬКО ССЫЛКИ! Но я не знаю, как этого добиться?

Одно из решений, которое я могу придумать, - это выделение байтового массива большого размера, тем самым создавая последовательное буферное хранилище памяти! И разработчик должен управлять тем, как получить некоторые данные int, хранящиеся в этом вручную созданном буфере (допустим, если мы моделируем как 2 байта / целое число) в 101 месте индекса, если в 2000 заранее выделенных байтах хранится 1000 объектов int!



Такая же функция желательна и для сложных типов данных. Хотя это может быть сложно при последовательном распределении памяти для сложных объектов, поскольку необходимо рассчитать размер структуры и предварительно выделить байтовый буфер (размер структуры * Ожидаемое количество элементов)



Я не могу придумать какой-либо другой эффективный способ или решение, возможное для последовательного размещения объектов (примитивных / сложных>. Кто-нибудь может мне помочь?


person Dhwanit    schedule 21.08.2013    source источник
comment
Вы пытаетесь решить проблему, которой не существует. Как вы думаете, почему текущая модель памяти Java неэффективна и вы могли бы добиться большего?   -  person Ravi K Thapliyal    schedule 21.08.2013
comment
Я бы хотел проверить Trove! Спасибо :)   -  person Dhwanit    schedule 21.08.2013


Ответы (4)


Не существует единого решения, отвечающего вашим требованиям.

Если вам нужна массивоподобная структура примитивного типа, вам нужно использовать массив этого примитивного типа или некоторый класс, который обертывает массив этого примитивного типа 1. Если вы попытаетесь реализовать настраиваемый класс, он не может быть универсальным (для примитивного типа), поскольку примитивные типы не могут использоваться в качестве параметров универсального типа. Следовательно, это не может быть ArrayList или любой другой тип, производный от Collection.

Если вам нужна массивоподобная структура ссылочного типа, вы можете использовать либо массив, либо ArrayList.


Короче говоря, если вы не желаете использовать типы оболочек (Integer и т. Д.):

  • Вы должны рассматривать примитивные и непримитивные типы отдельно.
  • Лучше всего (с точки зрения дизайна API и безопасности типов) рассматривать отдельные примитивные типы отдельно.

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

Ваша идея использования ByteBuffer по существу такая же, как и выше ... или хуже, если вы ожидаете, что код приложения выполняет все индексацию и кодирование / декодирование между байтами и условным базовым типом «массив». (И лучше начинать с byte[], а не с ByteBuffer.)


1 - Например, один из классов коллекции Trove.

person Stephen C    schedule 21.08.2013
comment
байтовый массив - это точка начала перед ByteBuffer. Но когда вы рассматриваете возможность последовательного хранения непримитивных типов, как Array, так и ArrayList могут сохранять последовательные ссылки на объекты, расположенные в случайных местах в памяти. В таком случае имеет смысл предварительно выделить массив байтов no. количество сложных объектов для хранения умножается на размер одного такого объекта. - person Dhwanit; 21.08.2013

Отказ от ответственности: это все равно не указано, так что это может быть случайностью.

В OpenJDK / Oracle JVM объекты размещаются в TLAB по порядку. После того, как он скопирован в оставшиеся / сохраненные пространства, он обнаруживается в обратном порядке. Это означает, что объекты, скорее всего, будут вместе в кеше.

Простое решение - использовать коллекцию на основе примитивов, такую ​​как Trove, где примитивы фактически находятся в массиве примитивов.

person Peter Lawrey    schedule 21.08.2013

Проектов примитивных коллекций очень много, вот некоторые из них:

  1. org.apache.commons .collections.primitives
  2. Высокопроизводительные примитивные коллекции
  3. Trove

Но имейте в виду, что, используя такие вещи, вы приближаетесь к реализации. Общего API для сбора примитивов не существует.

person Mikhail    schedule 21.08.2013

То, что вы пытаетесь сделать, технически невозможно из-за проблем с фрагментацией памяти. Подумай об этом. Если ваш буфер должен увеличиваться, ему необходимо перераспределить весь объем памяти, что приведет к быстрой фрагментации памяти, в результате чего у вас будет нехватка памяти, даже если технически у вас будет достаточно памяти. Ближе всего, что вы можете получить в обычной java, вероятно, java.nio.IntBuffer. Но, как говорили другие, вы пытаетесь решить проблему, которой не существует.

person Mikkel Løkke    schedule 21.08.2013
comment
Да, верно, но я думаю больше с точки зрения приложения, например, о реализации схемы хранения для базы данных хранилища столбцов, где отдельные элементы столбца, если они хранятся последовательно, обеспечат огромный прирост производительности при вычислении агрегатов. Операционный цикл для вычисления адреса следующего кортежа исключается, если ЦП знает, что все столбчатые данные хранятся последовательно, независимо от размера столбца. То же самое применимо к базе данных rowstore, где вам может потребоваться последовательный непримитивный тип хранилища для таких выгод. Я надеюсь, что смогу это передать. - person Dhwanit; 21.08.2013
comment
Если такая низкоуровневая оптимизация важна для вас, возможно, вам вообще не следует использовать Java. - person Mikkel Løkke; 22.08.2013
comment
Хорошо, кажется, теперь Java не дает такой гибкости для низкоуровневой оптимизации? - person Dhwanit; 23.08.2013
comment
Оптимизация в Java обычно сосредоточена на виртуальной машине, а не на байтовом коде. Идея заключается в том, что, поскольку JIT-компилятор знает, на какой платформе и архитектуре он работает и / или для которой он написан, он находится в лучшем положении для оптимизации. Это часть парадигмы «писать один раз / запускать где угодно». Если вы хотите запускать свое приложение только на фиксированной платформе (например, Windows / x64), Java предоставляет механизм JNI, который позволит вам выполнять низкоуровневую оптимизацию для конкретной платформы. - person Mikkel Løkke; 23.08.2013
comment
Хорошо .. Я проверю в JNI. Спасибо, Миккель :) - person Dhwanit; 23.08.2013