Разреженный массив с эффективным использованием памяти в Java

(Есть некоторые вопросы об эффективных по времени разреженных массивах, но я ищу эффективность использования памяти.)

Мне нужен эквивалент List<T> или Map<Integer,T>, который

  1. Может увеличиваться по требованию, просто устанавливая ключ больше, чем любой ранее встречавшийся. (Можно предположить, что ключи неотрицательны.)
  2. Примерно так же эффективно по памяти, как ArrayList<T>, в случае, если большинство индексов не null, т.е. когда фактические данные не очень разрежены.
  3. Когда индексы разрежены, занимает пространство, пропорциональное количеству индексов, отличных от null.
  4. Использует меньше памяти, чем HashMap<Integer,T> (поскольку это автоматически упаковывает ключи и, вероятно, не использует преимущества скалярного типа ключа).
  5. Может получить или установить элемент в амортизированном логарифмическом (N) времени, где N — количество записей: не обязательно линейное время, допустим двоичный поиск.
  6. Реализовано в невирусной библиотеке Java с открытым исходным кодом (предпочтительно в Maven Central).

Кто-нибудь знает о таком служебном классе?

Я ожидал, что он будет в коллекции Commons, но, похоже, этого не произошло.

Я наткнулся на org.apache.commons.math.util.OpenIntToFieldHashMap, который выглядит почти правильно, за исключением того, что тип значения — FieldElement, который кажется необоснованным; Я просто хочу T extends Object. Похоже, что было бы легко отредактировать его исходный код, чтобы сделать его более общим, хотя я бы предпочел использовать двоичную зависимость, если она доступна.


person Jesse Glick    schedule 27.09.2012    source источник


Ответы (5)


Я бы попробовал с коллекциями trove, есть TIntObjectMap, который может работать в ваших целях.

person Jack    schedule 27.09.2012
comment
Выглядит хорошо. Я попытался адаптировать OpenIntToFieldHashMap к общему типу значения, который, кажется, работал с ~ 10-минутной работой, но он работает лишь незначительно лучше, чем TIntObjectMap. - person Jesse Glick; 27.09.2012

Я бы посмотрел на реализацию Android SparseArray для вдохновения. Вы можете просмотреть исходный код, загрузив исходный код AOSP здесь http://source.android.com/source/downloading.html

person Florian Laplantif    schedule 22.04.2013
comment
code.google.com/p/android-source-browsing/source/browse/core/ выглядит подходящим — амортизированное время работы не документировано, но из проверки я предполагаю, что оно логарифмическое — и соответствует ASL ​​2.0, что нормально. К сожалению, я не знаю, что он находится в Central, и хотел бы, чтобы он был отделен от несвязанных вещей, таких как поддержка Android Bluetooth, которая находится в одном и том же корне исходного кода. - person Jesse Glick; 26.07.2013
comment
Вот автономная версия, в которой используется весь необходимый код из android "nofollow noreferrer">github.com/frostwire/frostwire-jlibtorrent/blob/ - person Gubatron; 28.10.2014
comment
Возможно, вы ищете более точно SparseIntArray, где вы избегаете затрат на упаковку/распаковку индексов разработчика. android.com/reference/android/util/SparseIntArray И да, исходный код доступен и имеет простую и удобную лицензию, если вы хотите извлечь его из базы кода Google и адаптировать. - person Yann TM; 11.12.2019

Я предлагаю вам использовать OpenIntObjectHashMap из библиотеки Colt. Ссылка

person abhi    schedule 13.05.2014
comment
Спасибо за совет. Он действительно потребляет умеренно, но значительно меньше места, чем альтернативы. Я включил это в свой пересмотренный тестовый пример. - person Jesse Glick; 15.05.2014

Я сохранил свой тестовый пример как jglick/inthashmap. Результаты, достижения:

HashMap size: 1017504
TIntObjectMap size: 853216
IntHashMap size: 846984
OpenIntObjectHashMap size: 760472
person Jesse Glick    schedule 27.09.2012
comment
Где найти IntHashMap? - person oleh; 01.03.2013
comment
@oleh, вероятно, Apache Commons (?) - person Karussell; 05.04.2013
comment
Извините, IntHashMap было моей адаптацией OpenIntToFieldHashMap из Commons Math. Поскольку это было чуть лучше, чем TIntObjectMap, я отклонил этот подход. - person Jesse Glick; 26.07.2013
comment
@leventov интересно. Отвечает на другой набор вопросов, чем я задавал здесь, но является хорошим источником для изучения потенциальных реализаций. - person Jesse Glick; 18.08.2014
comment
Почему разные. Он показывает среднее относительное перерасход памяти для карт int -> int в библиотеках, что хорошо коррелирует с int -> obj, поскольку специализации однородны во всех библиотеках. - person leventov; 18.08.2014
comment
Ну, вы также измеряете скорость доступа, которую я не считал актуальной (пока она логарифмическая); и я сравниваю память с неразреженным ArrayList<T>, который будет вдвое меньше «теоретического минимума» в более общем случае, который вы рассматривали. - person Jesse Glick; 19.08.2014
comment
В вашем ответе сравниваются только разные реализации хеш-таблиц. Я сослался на другое сравнение, которое включает все протестированные вами импликации и многое другое. - person leventov; 21.08.2014

Поздно с этим вопросом, но есть IntMap в libgdx, который использует хеширование с кукушкой. Если что, было бы интересно сравнить с другими.

person NateS    schedule 19.09.2018