Как хранить целые числа в диапазоне от 0 до 9 всего в 4 битах и ​​использовать то же самое, что и ключ в HashMap?

Меня попросили придумать решение, в котором у вас есть файл, в котором каждая строка представляет 10-значный номер телефона, и нам нужно указать, присутствует ли данный 10-значный номер телефона в файле или нет.

Я придумал структуру Trie Data, в которой каждый дочерний элемент представляет собой не что иное, как карту целого числа в качестве ключа и Trie в качестве значения.

class Trie{

   boolean isEnd;
   Map<Integer, Trie> map = new HashMap<>();
}

Я также могу использовать int[] arr для хранения дочерних элементов.

Поскольку у нас есть только числа от 0 до 9, мы можем хранить эти числа только в 4 битах. Зачем брать int или Integer в качестве типа данных. Как тут уменьшить память?

Как мы можем хранить эти числа в карте или массиве, но не принимая во внимание, так как в конечном итоге мы потеряем много памяти.

Более того, есть ли лучшее решение, чем Trie?

Если ваши ключи Map являются числами, и они ограничены небольшим количеством, то массив или список как структура имеют такую ​​же производительность чтения, как и соответствующая карта (O (1)), но с меньшими накладными расходами.

Mark Jeronimus 26.06.2019 16:59

Мои ключи карты - это не весь номер телефона. Каждая цифра числа является ключевой, а остальные цифры - дочерними,

PolygotP 26.06.2019 21:37

Хотя вы можете представить цифру всего 4 битами, в Java нет собственного 4-битного типа данных. Таким образом, вы не можете сохранить память таким образом. Однако вы можете хранить две цифры в одном 8-битном значении. Но использование здесь trie, вероятно, не лучший вариант из-за ограничений памяти. Почему не Map<long, boolean>? Конечно, вы тратите один байт boolean на каждое число, но это намного меньше памяти, которую вы будете использовать для хранения указателей в своем дереве.

Jim Mischel 27.06.2019 07:01
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
3
265
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы стремитесь к эффективности памяти, я бы посоветовал против использовать trie и порекомендовать другую структуру данных. Насколько я понимаю, вас интересуют только ответы на запросы вида "видел ли я раньше этот номер телефона?" Хотя вы могли бы сделать это, рассматривая телефонные номера как строки и помещая их все в дерево, вы не воспользуетесь преимуществами операций, для поддержки которых предназначены попытки (быстрый поиск префиксов, извлечение элементов в отсортированном порядке и т. д. ), поэтому вы будете платить за то, чем не будете пользоваться.

Кроме того, давайте подумаем об использовании пространства в дереве. Даже если у каждого телефонного номера есть длинный общий префикс, каждому узлу в дереве требуется место для хранения дочерних указателей. Если вы храните хотя бы один (64-разрядный) указатель на узел, вы используете тот же объем пространства, который вы бы использовали для хранения 10-значного номера телефона (который удобно вписывается в 64-разрядное целое число). Если телефонные номера не имеют длинных общих префиксов, вы потенциально храните десять указателей на номер, что приводит к огромному увеличению пространства, независимо от того, насколько велики ключи хеш-таблицы.

Вместо того, чтобы бросать вещи в три, я бы подумал об использовании простой, ванильной хеш-таблицы. В конце концов, хэш-таблицы специально оптимизированы для поддержки запросов о членстве и только запросов о членстве. Хеширование телефонных номеров не должно вызывать особых затруднений, так как их можно упаковать в 64-битные целые числа и хешировать с помощью множества простых методов хеширования. Это позволяет вам контролировать, какой компромисс между временем и пространством вы хотите сделать (большие размеры таблиц увеличивают память и уменьшают время, меньшие таблицы увеличивают время и уменьшают память).

Спасибо за объяснение, не используя trie. Но в хеш-таблице мы также тратим впустую память поля «значение», поскольку мы ее не используем. Во-вторых, как насчет моей первой части вопросов о хранении чисел от 0 до 9 в 4 битах в java? В случае, если вы можете помочь мне в этом.

PolygotP 26.06.2019 21:40

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

templatetypedef 27.06.2019 14:47

Он имеет в виду, что хеш-таблица хранит ключ-> значение, где только ключ является полезной нагрузкой. Вместо этого используйте HashSet. По иронии судьбы, HashSet имеет немного больший объем памяти (только на фиксированное количество байтов), поскольку он использует HashMap внутри и не использует поля «значение».

Mark Jeronimus 28.06.2019 13:59

В зависимости от того, как все реализовано, иногда контейнерам на основе хэшей все еще нужны некоторые вспомогательные управляющие слова, связанные с каждой записью, для хранения данных, таких как «этот слот пуст?», «насколько далеко этот элемент от своего домашнего слота?» и т. д. Даже с такими накладными расходами памяти это все же, вероятно, лучший маршрут, чем trie.

templatetypedef 28.06.2019 16:46

Другие вопросы по теме