Создать хэш из строки и 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.

Ответ 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);
}