Создать хэш из строки и int
Я помню, что затмение и идея имеют этот шаблон для автоматического создания объекта hashCode на основе его атрибутов.
Одна из стратегий, если используется число и строка, выглядит примерно так.
return stringValue.hashCode() + intValue * 32;
Что-то вроде этого.
У меня нет ни затмения, ни идеи, и я бы хотел создать такую функцию.
ИЗМЕНИТЬ
Основываясь на ответах, я создаю этот мини-класс
class StringInt {
private final String s;
private final int i;
static StringInt valueOf( String string , int value ) {
return new StringInt( string, value );
}
private StringInt( String string, int value ) {
this.s = string;
this.i = value;
}
public boolean equals( Object o ) {
if( o != null && o instanceof StringInt ){
StringInt other = ( StringInt ) o;
return this.s == other.s && this.i == other.i;
}
return false;
}
public int hashCode() {
return s != null ? s.hashCode() * 37 + i : i;
}
}
Этот класс должен использоваться как ключ для большой карты памяти ( > 10k элементов). Я не хочу каждый раз перебирать их, чтобы определить, совпадают ли строки и int.
Спасибо.
ps.. mmh, вероятно, это должны быть имена StringIntKey.
Ответы
Ответ 1
Используйте Apache Commons HashcodeBuilder:
public int hashCode() {
new HashCodeBuilder(17, 37).
append(myString).
append(myInt);
}
Ссылка здесь:
http://commons.apache.org/lang/api-2.3/org/apache/commons/lang/builder/HashCodeBuilder.html
И здесь:
http://www.koders.com/java/fidCE4E86F23847AE93909CE105394B668DDB0F491A.aspx
Ответ 2
Или, если вы не хотите добавлять другую библиотеку, сделайте следующее:
public int hashCode() {
StringBuilder builder = new StringBuilder();
builder.append(myString);
builder.append(myInteger);
return builder.toString().hashCode();
}
Ответ 3
Eclipse всегда выполняет примерно одну и ту же функцию хеширования, здесь пример для класса с полями in и String as
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + this.interger;
result = prime * result + ((this.string == null) ? 0 : this.string.hashCode());
return result;
}
Они всегда выбирают 31 как простое, а затем несколько строятся в хэш-функциях или значение, если это примитив. Нечто подобное было бы трудно создать как метод.
public int hashCode(Object ... things) {
final int prime = 31;
int result = 1;
for(Object thing : things) {
result = prime * result + thing.hashCode();
}
return result;
}
Ответ 4
Метод хэш-кода - это то, что потенциально можно назвать много раз, и поэтому стоит оптимизировать. Если вычисление сложное, рассмотрите memoizing хэш-значение. Кроме того, избегайте делать вещи, которые влекут за собой больше вычислений, чем это необходимо. (Например, решение StringBuilder тратит большую часть времени на создание временной строки.)
Другая вещь, которую я хочу отметить, - это то, что качество хэш важно. Вы хотите избежать любого алгоритма hashcode, который отображает множество общих ключей. Если это произойдет, поиск в хэш-таблице больше не может быть O (1). (В худшем случае это будет O (N)... т.е. Эквивалентно линейному поиску!). Вот пример плохой хэш-функции:
int hashcode() {
int hash = 1;
for (int val : this.values) {
hash = hash * value;
}
return hash;
}
Рассмотрим, что произойдет, если элемент this.values
равен нулю...
Ответ 5
В дополнение к последнему редактированию, если скорость поиска важнее, чем проблемы с хранением, вы можете предварительно вычислить и сохранить хеш-код при построении класса StringInt
. Это безопасно, поскольку вы помечали поля String
и int
как final
, а также при условии, что String
является неизменяемым.
Кроме того, вы можете оптимизировать свой метод equals
, проверив, что сравниваемый объект == this
перед выполнением полного сравнения. Я бы также рекомендовал сначала провести более дешевое сравнение на основе int перед сравнением строковых полей.
Еще одно окончательное предложение: вы можете изменить свой метод valueOf(String, int)
либо построить StringInt
, либо вернуть ранее созданный экземпляр, если он уже существует с теми же значениями String
и int. Это делает строительство более дорогостоящим, но сравнение очень дешевым, поскольку вы можете сравнить StringInt
с помощью "==", зная, что никакие два StringInt
никогда не будут созданы с теми же значениями String
и int
.
Ответ 6
Вы также можете использовать класс Objects
из пакета java.util.Objects
для быстрого получения хэш-кода.
@Override
public int hashCode() {
return Objects.hash(this.string, this.integerValue, this.otherDataTypes);
}