Различное поколение Enum HashCode? - PullRequest
7 голосов
/ 24 февраля 2012

Почему существуют разные значения hashCode при каждом запуске java main?Посмотрите приведенный ниже пример кода.

interface testInt{

    public int getValue();
}

enum test  implements testInt{
    A( 1 ),
    B( 2 );

    private int value;

    private test( int value ) {
        this.value = value;
    }

    public int getValue() {
        return this.value;
    }
}

При каждом запуске

public static void main( String[] args ) {
     System.out.println( test.A.hashCode() );
}

на консоли будут отображаться разные значения.Почему это несоответствие?

Ответы [ 5 ]

4 голосов
/ 24 февраля 2012

Если вы хотите использовать одно и то же значение каждый раз, используйте .ordinal() или даже лучше, используйте getValue(), как у вас. Вы можете переопределить hashCode () по умолчанию, то есть присвоить ему число, основанное на способе создания объекта.

4 голосов
/ 24 февраля 2012

"Не требуется, чтобы хеш-значения были согласованными между различными реализациями Java или даже между различными запусками выполнения одной и той же программы."

http://en.wikipedia.org/wiki/Java_hashCode%28%29

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Object.html#hashCode%28%29

public static void main( String[] args ) {
     System.out.println( test.A.hashCode() );
     System.out.println( test.A.hashCode() );
}

Этот код теперь будет производить тот же хэш-код.

2 голосов
/ 24 февраля 2012

Javadocs ясно заявляет об этом.Из javadocs для метода хэш-кода в классе Object c

Насколько это практически целесообразно, метод hashCode, определенный в классе Object, возвращает различные целые числа для различных объектов.(Обычно это реализуется путем преобразования внутреннего адреса объекта в целое число, но этот метод реализации не требуется языком программирования JavaTM.)

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

В зависимости от ваших потребностей, если вы хотите, чтобы метод hashcode () возвращал одно и то же значение при вызовах jvm, вы должны переопределить методвернуть пользовательское значение.Однако вы должны знать, что это может привести к катастрофическим последствиям, если объект будет использоваться в коллекциях на основе хеша (повышенные шансы на столкновение хеша).

0 голосов
/ 24 февраля 2012

Enum.hashCode не определен, чтобы возвращать какие-либо конкретные значения (кроме соблюдения правил Object.hashCode), и общие реализации не делают ничего особенного.

Почему?Если вы использовали перечисления (только) в HashSet или в качестве ключа в HashMap, то вместо этого вам следует использовать оптимизированные EnumSet или EnumMap.Теперь рассмотрим, будет ли перечисление использоваться вместе с другими типами в HashSet.Возможно, у вас есть несколько «стандартных опций» для реализации интерфейса, но другие могут прийти со своими опциями.Все безгражданство будет делать.Несколько типов перечислений в одном HashSet.Если Enum использовал порядковые числа для значения хеша, то у вас будут общие коллизии.Использование System.identityHashCode позволяет надежно уменьшить коллизии.

public interface Option {
}
public enum StandardOptions implements Option {
    A, B, C
}
enum CustomOptions {
    P, Q, R
}
enum MoreOptions {
    X, Y, Z
}

    Set<Option> options = new HashSet<>();
    options.add(A);
    options.add(P);
    options.add(X);

Мы действительно не хотим A.hashCode() == P.hashCode() == X.hashCode().

0 голосов
/ 24 февраля 2012

Может быть, некоторые реализации JVM в основном возвращают Enum.ordinal() (что также может быть большим hashCode), но это ничего не изменит. Значение hashCode() не обязательно должно быть одинаковым для всех исполнений или JVM. Единственный требуемый контракт описан в JavaDocs Object.hashCode() - и именно реализация в Object используется в enum.

Также обратите внимание, что реализация интерфейса не имеет ничего общего с hashCode():

public class TestEnum {

    public static void main(String[] args) {
        System.out.println(Silly.B.hashCode());
        System.out.println(Silly.C.hashCode());
        System.out.println(Silly.D.hashCode());
    }
}

enum Silly {
    B, C, D
}

Эта программа также возвращает разные hashCode() с при каждом запуске.

...