2010-04-15 12 views
12

Estoy buscando una solución para generar una suma de comprobación para cualquier tipo de objeto Java, que sigue siendo el mismo para cada ejecución de una aplicación que produce el mismo objeto.Cómo generar una suma de comprobación para un objeto java

he probado con Object.hashCode(), pero la API dice

.... Este número entero no tiene que mantener la coherencia de una ejecución de una aplicación a otra ejecución de la misma aplicación.

+0

se puede añadir un enlace a la cita? – Roman

+0

@Roman: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html#hashCode%28%29 –

+7

'int checksum (Object o) {return 1;} 'llena tus requisitos :-) –

Respuesta

7

Tuve un problema similar (generando un buen hashcode para archivos XML) y descubrí que la mejor solución es usar MD5 a través de MessageDigest o en caso de que necesite algo más rápido: Fast MD5. Tenga en cuenta que incluso si Object.hashCode fuera el mismo siempre, de todos modos, es demasiado corto (solo 32 bits) para garantizar una gran exclusividad. Creo que 64 bits es un mínimo para calcular un buen código hash. Tenga en cuenta que MD5 genera código hash de 128 bits de longitud, que debería ser aún más necesario en esta situación.

Por supuesto, para usar MessageDigest necesita serializar (en su caso, Marshall) el objeto primero.

+0

gracias a todos por sus respuestas. Calculo un MD5 a partir de la solicitud marshalled. – Alex

5

Creo que deberías mirar serialization. El mecanismo de serialización necesita resolver un problema similar, para que pueda ver cómo se implementa.

Pero si describes el problema que tratas de resolver, es probable que obtienes una solución más precisa.

4

Si controla la fuente, puede implementar hashCode() para que sea consistente de una ejecución a otra.

3

¿Desea poder hacer esto para todos objetos de Java?

En ese caso hashCode() no funciona.

Para algunas clases hashCode() tiene una definición más estricta que garantiza igualdad en las ejecuciones. Por ejemplo, String tiene una implementación bien definida hashCode. Del mismo modo List y Set han valores bien definido, siempre que todos los objetos que contienen también tienen valores bien definidos (tenga en cuenta que el general Collection.hashCode() hace no requieren el valor a ser bien definido).

Para otras clases, tendrá que usar la reflexión recursivamente con alguna fórmula bien definida para crear una suma de comprobación.

2

Hashcode está bien. O bien la clase dada reemplaza equals y también, como exige el contrato, hashcode. Por contrato, si equals devuelve true, el código hash debe ser el mismo.
O la clase no anula equals. En este caso, las diferentes ejecuciones de su aplicación no pueden producir mismo objeto, por lo que no hay problema.
El único problema es que algunas clases (incluso desde la API de Java) rompen el contrato para equals.

2

La biblioteca común de Apache ofrece una clase HashCodeBuilder que ayuda a crear un código hash que llena sus requisitos de las propiedades de clase.

Ejemplo:

public int checksum() { 
    // you pick a hard-coded, randomly chosen, non-zero, odd number 
    // ideally different for each class 
    return new HashCodeBuilder(17, 37). 
     append(property1). 
     append(property2). 
     append(property3). 
     toHashCode(); 
    } 

Ver Commons Lang API

2

Si usted es F está utilizando Eclipse IDE entonces tiene acciones (bajo menú de fuente) para generar código hash y las funciones de igual. Le permite elegir los atributos de la clase que desea en el código hash. Esto es similar al uso del enfoque HashCodeBuilder que ya se sugirió.

Como alternativa, puede transmitir el objeto a una matriz de bytes y generar un MD5 de eso.

8

Ejemplo

 
private BigInteger checksum(Object obj) throws IOException, NoSuchAlgorithmException { 

    if (obj == null) { 
     return BigInteger.ZERO; 
    } 

    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    ObjectOutputStream oos = new ObjectOutputStream(baos); 
    oos.writeObject(obj); 
    oos.close(); 

    MessageDigest m = MessageDigest.getInstance("SHA1"); 
    m.update(baos.toByteArray()); 

    return new BigInteger(1, m.digest()); 
} 
7
public static String getChecksum(Serializable object) throws IOException, NoSuchAlgorithmException { 
    ByteArrayOutputStream baos = null; 
    ObjectOutputStream oos = null; 
    try { 
     baos = new ByteArrayOutputStream(); 
     oos = new ObjectOutputStream(baos); 
     oos.writeObject(object); 
     MessageDigest md = MessageDigest.getInstance("MD5"); 
     byte[] thedigest = md.digest(baos.toByteArray()); 
     return DatatypeConverter.printHexBinary(thedigest); 
    } finally { 
     oos.close(); 
     baos.close(); 
    } 
} 
0
  1. Objeto -> cadena (por ejemplo, GSON - usted no tendrá que escribir la serialización no enumerar todos los campos de su clase)

  2. Cadena .hashCode() -> int (En lugar de Object.hashCode()! Esta realización de hashCode() depende del contenido de String, no de la dirección en la memoria --- puede usarlo en diferentes lanzamientos de aplicaciones, diferentes hilos, etc.)

(o 2. Cadena -> MD5)

Cuestiones relacionadas