Я могу только предположить, что причина, по которой вы хотите избежать перефразирования всего, состоит в том, что результирующая операция с высокой задержкой не является проблемой пропускной способности, а вместо этого является проблемой для отзывчивости (в человеческом или в SLA-смысле)
Теоретически вы можете использовать модифицированную хеш-таблицу с закрытой адресацией, например:
- помните все предыдущие размеры, где элементы были добавлены
- При изменении размера сохраняйте старые корзины, связанные с ними, посредством карты sizeWhenUsed -> buckets (очевидно, если корзины пустые, не нужно беспокоиться)
- Инвариантное отображение ключа k существует только в одной из «внутренних хеш-таблиц» в любое время.
- при добавлении значения вы должны сначала найти его на всех других картах, чтобы определить, существует ли запись и сопоставлена ли она. Если это удалить его из старого и добавить его в новый.
- если внутренняя карта становится пустой / ниже определенного размера, она должна быть удалена, а оставшиеся элементы перемещены в текущую хэш-таблицу.
- До тех пор, пока число внутренних хэшей остается постоянным, это не повлияет на поведение O большой структуры данных во времени, хотя будет в памяти.
- Это, однако, повлияет на фактическую производительность, так как X должны быть выполнены дополнительные проверки, где X - количество сохраненных старых хешей.
- Если потраченное впустую пространство списка сегментов (сами контейнеры будут нулевыми, если они пустые, а затраты равны нулю, если не заполнены) станут значительными (используйте для этого коэффициент помадки), то в какой-то момент повторного анализа вам, возможно, придется принять попадание вещей в текущую таблицу, если вы не готовы тратить практически неограниченную память.
Уменьшение размера хеша только будет функционировать желаемым образом (освобождая память), если вы захотите перефразировать. Это неизбежно.
Возможно, вы могли бы использовать некоторые сложные дополнительные данные в рамках открытой схемы адресации, чтобы «пометить», какой из внутренних хэшей использовалась ячейка, но удаление было бы чрезвычайно сложным, чтобы получить правильные результаты, и было бы очень дорого, если бы Вы просто оставили их как пустое место. Я бы никогда не попробовал это.
Я бы не советовал использовать первый метод, если только базовые данные не занимают очень мало времени в хэше, поэтому связанная отток будет иметь тенденцию постоянно «стирать» хэши более старого размера. Вполне вероятно, что хеш, настроенный именно на такое поведение и настроенный на соответствующий размер, будет работать намного лучше.
Поскольку вышеприведенная схема просто торгует потраченной впустую памятью и пропускной способностью для сокращения дорогостоящих операций со спекулятивным (в лучшем случае) шансом сокращения этих потерь, я бы предложил просто предварительно задать размер хэша, который будет больше требуемого, и, следовательно, никогда не изменял размер быть более разумным вариантом.