2012-02-24 15 views
5

¿Por qué hay diferentes valores hashCode por cada vez que ejecuta una Java principal? Mire el código de ejemplo a continuación.Diferente generación de HashCode Enum?

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; 
    } 
} 

Para cada vez que se ejecuta,

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

habrá diferentes valores impresos en la consola. ¿Por qué esa inconsistencia?

Respuesta

3

Si quiere el mismo valor cada vez, use .ordinal() o incluso mejor, use getValue() como usted. Puede anular hashCode() del valor predeterminado, que es darle un número que se basa en la forma en que se creó el objeto.

+0

Sí, ahora estoy usando getValue como una solución. Acabo de crear la publicación para ver por qué diferentes hashCodes al implementar una interfaz. Gracias. –

2

Los javadocs afirman claramente que. De los javadocs para el método de código hash en el objeto c clase

Tanto como sea razonablemente práctico, el método hashCode definido por la clase Object no devolver enteros diferentes para objetos distintos. (Esto se implementa típicamente mediante la conversión de la dirección interna del objeto en un entero, pero esta técnica de implementación no es requerida por el lenguaje de programación Java ™.)

Así que a través de diferentes carreras de su código de demostración, la dirección interna puede varían y, por lo tanto, es perfectamente normal que vea valores diferentes.

Dependiendo de sus necesidades, si desea que el método hashcode() devuelva el mismo valor en las invocaciones de jvm, debe anular el método para devolver el valor personalizado. Sin embargo, debe saber que esto podría ser catastrófico si el objeto se va a utilizar en colecciones basadas en hash (mayores posibilidades de colisión hash).

+0

Como dije. Lo que me trajo aquí fue el hecho de que, enum simples, en mi Oracle JVM7, devolvía el mismo hashCode en diferentes ejecuciones. Pero cuando se cambiaba a enum especializado, el código hash era diferente para cada ejecución. –

3

"No es necesario que los valores de hash sean consistentes entre diferentes implementaciones de Java, o incluso entre ejecuciones de ejecución diferentes del mismo programa."

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()); 
} 

Este código producirá ahora mismo código hash.

+0

Ok, pero eso solo ocurre si tienes una enumeración que implementa una interfaz. –

+0

No necesariamente. Si está comparando con la producción de código hash de una cadena (u otra cosa) entre la ejecución del programa, el hecho de que generen el mismo código puede ser una coincidencia. – jn1kk

+0

Supongo que la coincidencia no es la palabra correcta aquí. Realmente devuelve el mismo valor hashCode para enumeraciones que no implementa ninguna interfaz. Eso es lo que me señaló aquí. –

0

Quizás algunas implementaciones de JVM básicamente devuelvan Enum.ordinal() (lo que también sería genial hashCode), pero no cambiaría nada de manera efectiva. hashCode() valor no tiene que ser coherente en todas las ejecuciones o JVM. El único contrato requerido se describe en los JavaDocs de Object.hashCode(), y es la implementación en Object que se utiliza en enum.

También tenga en cuenta que la implementación de una interfaz no tiene nada que ver con 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 
} 

Este programa también devuelve diferentes hashCode() s en cada carrera.

+0

Ok, Silly.B.hashCode, devolvería lo mismo y no diferentes hasCodes. Si implementar una interfaz no tiene nada que ver con hashCode, ¿por qué sucede eso? ¿Ves a dónde voy? Silly.B.hashCode es igual en diferentes ejecuciones, pero si haces que Silly implements tenga una interfaz simple, entonces habrá diferentes hashCodes para Silly.A –

+0

@ VíctorHugo: ¿qué JVM estás usando? El 1.6.0_26-b03 a veces devuelve los mismos valores, a veces diferentes, pero con certeza no son los mismos todo el tiempo ... –

+0

JVM, jdk1.7.0_02 (Oracle) –

0

Enum.hashCode no está definido para devolver ningún valor específico (aparte de obedecer las reglas de Object.hashCode), y las implementaciones comunes no hacen nada especial.

¿Por qué? Si usaba las enumeraciones (solo) en un HashSet o como una clave en un HashMap, debería usar el optimizado EnumSet o EnumMap. Ahora considere si la enumeración se utilizará junto con otros tipos en un HashSet. Quizás tenga algunas "opciones estándar" para implementar una interfaz, pero otras pueden incluir sus propias opciones. Cualquier cosa sin estado servirá. Múltiples tipos de enumeración en uno HashSet. Si Enum hubiera usado ordinales para el valor hash, entonces tendrá colisiones comunes. El uso de System.identityHashCode reduce las colisiones de manera robusta.

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); 

Realmente no queremos A.hashCode() == P.hashCode() == X.hashCode().