TGViewer
Android under the hood Android under the hood @android_under_the_hood · 1.53K subscribers
Post #128 2.74K
Хэш-таблицы, часть I.

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

// храним картинки в кэше, в качестве ключа используется адрес
val imageCache = mutableMapOf<Uri, Bitmap>()

// храним файлы в кэше, в качестве ключа также используется адрес
val downloadCache = mutableMapOf<Uri, File>()


Для реализации подобной структуры данных часто используется обычный массив, индексы которого вычисляются с помощью хэш функции, отсюда название хэш-таблица:

val images = Array(10) { "" }

val url = "https://images.com/image0"
val image = downloadImage(url)
// за счет практически мгновенного вычисления индекса в хэш-таблице время добавления и изменения значений в среднем составляет O(1)
val index = hash(url)
images[index] = image

fun downloadImage(url: String) { ... }

// простая хэш-функция
fun hash(url: String): Int {
return url.last().digitToInt()
}


В примере достаточно примитивная хэш функция, которая просто извлекает цифру из строки и принимает ее за индекс.

В боевой же реализации HashMap используется другая хэш-функция, а также метод hashCode():

// что-то типо модульного деления, ограничивает индекс до размера массива - 1
int index = hash(key) & (size - 1);

// боевая версия хэш-функции
static final int hash(Object key) {
if (key == null) return 0;

// о переопределении этого метода уже наверно книги есть, короче если он плохо написан индексы будут одинаковые, а это коллизия и ее надо как-то решать
int h = key.hashCode();
// смешивает младшие биты со старшими
return h ^ (h >>> 16);
}


Смешивание младших и старших битов нужно для более равномерного распределения индексов, так как при небольшом размере HashMap старшие биты могут просто обрезаться и не учитываться из-за операции по модулю.

В следующем посте поговорим о коллизиях и способах их решения, короче продолжение следует...
  • 👍 14
  • 😁 2
More from @android_under_the_hood
  1. Oct 4, 2026Всем привет, хочу поделиться проектом, который запустил 1 октября — ЗдесьЯ. Это цифровая с…
  2. Oct 2, 2026Kotlin lambdas, часть I. До версии Kotlin 2.0 лямбды компилировались в анонимные классы, р…
  3. Sep 27, 2026Делегат свойства в Kotlin. В Kotlin есть конструкция, которой нет в JVM: var name by NameD…
  4. Sep 23, 2026val vs var под капотом. На уровне Kotlin все просто: val x = 10 var y = 20 y = 30 // компи…
  5. Sep 20, 2026Возвращение Прошло уже полгода с последней записи на канале. За это время в моей жизни про…
  6. Feb 5, 2026Пару фактов о Go, часть II. 4) Вместо Kotlin Nullability указатели как в С/C++, то есть об…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →