Как я могу сгенерировать уникальный int из уникальной строки?

У меня есть объект со String, который содержит уникальный идентификатор. (например, "ocx7gf" или "67hfs8" ) Мне нужно предоставить ему реализацию int hascode(), которая будет уникальной, очевидно.

как я могу свести строку к уникальному int самым простым/быстрым способом?

10x.

Изменить - ОК. Я уже знаю, что String.hashcode возможен. Но это не рекомендуется ни в каком месте. На самом деле, если какой-либо другой метод не рекомендуется - должен ли я использовать его или нет, если у меня есть объект в коллекции, и мне нужен хэш-код. должен ли я конкатрировать его с другой строкой, чтобы сделать ее более успешной?

Ответ 1

Нет, вам не нужно иметь реализацию, которая возвращает уникальное значение "очевидно", так как очевидно, что большинство реализаций будет нарушено.

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

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

Изменить: при хорошем разбросе бит.

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

Кроме того, хеши, как правило, повторно хешируются, поэтому наше 32-разрядное число может быть уменьшено до, например, один в диапазоне от 0 до 22, и мы хотим как можно лучше распределить его по возможности.

Мы также хотим сбалансировать это, не задумываясь так долго, чтобы вычислить наш хэш, что он становится узким местом сам по себе. Неправильный балансирующий акт.

Классический пример плохого хеш-метода - это один из координированных паров X, Y ints, который делает:

return X ^ Y;

Хотя это делает хорошую работу по возврату 2 ^ 32 возможных значений из 4 ^ 32 возможных входов, в реальном мире довольно часто встречаются множества координат, где X и Y равны ({0, 0}, {1, 1}, {2, 2} и т.д.), Которые все хеш равны нулю, или совпадающие пары ({2,3} и {3, 2}), которые будут иметь хэш с тем же номером. Скорее всего, нам лучше обслуживать:

return ((X << 16) | (x >> 16)) ^ Y;

Теперь есть столько же возможных значений, для которых это ужасно, чем для первого, но оно, как правило, лучше работает в реальных случаях.

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

Следовательно, если я, например, знал, что данная строка всегда будет состоять из 6 нечувствительных к регистру символов в диапазоне [az] или [0-9] (что кажется вам, но это не ясно из ваш вопрос, что он делает), тогда я мог бы использовать алгоритм, которому присваивалось значение от 0 до 35 (36 возможных значений для каждого символа) каждому символу, а затем проходил через строку, каждый раз умножая текущее значение на 36 и добавляя значение следующего char.

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

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

Одно из преимуществ заключается в том, что, поскольку он является идентификатором в себе, то, по-видимому, ни один другой неравный объект не имеет одинакового идентификатора, и, следовательно, никаких других свойств не требуется. Это не всегда выполняется.

Ответ 2

Вы не можете получить уникальное целое число из строки неограниченной длины. Существует 4 миллиарда (2 ^ 32) уникальных целых числа, но почти бесконечное количество уникальных строк.

String.hashCode() не даст вам уникальных целых чисел, но он сделает все возможное, чтобы дать вам разные результаты на основе входной строки.

ИЗМЕНИТЬ

Ваш отредактированный вопрос говорит, что String.hashCode() не рекомендуется. Это неверно, рекомендуется, если у вас нет особых причин не использовать его. Если у вас есть особая причина, предоставьте подробную информацию.

Ответ 3

Похоже, у вас есть номер базы-36 (a-z + 0-9). Почему бы не преобразовать его в int с помощью Integer.parseInt(s, 36)? Очевидно, что, если существует слишком много уникальных идентификаторов, оно не будет вписываться в int, но в этом случае вам не повезло с уникальными целыми числами, и вам нужно будет использовать String.hashCode(), что делает все возможное для быть близким к уникальному.

Ответ 4

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

Скажем, у вас есть 32-битное целое число и 64-символьный набор символов для ваших строк. Это означает шесть бит на символ. Это позволит вам сохранить пять символов в целое число. Более того, и это не подойдет.

Ответ 5

Один из способов сделать это - назначить каждой букве значение, и каждое место строки принадлежит ей, то есть a = 1, b = 2 и т.д., тогда все в первой цифре (читается слева направо) умножить на простое число, следующее следующее простое число и т.д., так что конечная цифра умножается на число, большее, чем число возможных подмножеств в этой цифре (26 + 1 для пробела или 52 + 1 с capitols и т.д. для других поддерживаемых символов). Если число сопоставляется с первыми цифрами (крайний левый символ), любое число, которое вы генерируете, из уникальной строки, отображающей обратно до 1 или 6, независимо от первой буквы, дает уникальное значение.

Собака может быть 30,3 (15), 101 (7) или 782, в то время как Бог 33,3 (15), 101 (4) или 482. Что более важно, чем генерируемые уникальные строки, они могут быть полезны в генерации, если исходная цифра сохраняется, например, 30 (782) будет уникальной для некоторых 12 (782) в целях дифференцирования таких строк, если вам удастся преодолеть уникальные возможности. Собака всегда была собакой, но она никогда не была бы Кошкой или Мышей.