2010-04-15 5 views
12

Я ищу решение для создания контрольной суммы для любого типа объекта Java, которая остается неизменной для каждого выполнения приложения, которое создает тот же объект.Как сгенерировать контрольную сумму для объекта java

Я пробовал с Object.hashCode(), но апи говорит

.... Это число не должно оставаться последовательным от одного исполнения приложения другому исполнения одного и того же приложения.

+0

Вы можете добавить ссылку на цитату? – 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;} 'заполняет ваши требования :-) –

ответ

7

У меня была аналогичная проблема (генерирование хорошего хэш-кода для файлов XML), и я выяснил, что лучшим решением является использование MD5 до MessageDigest или в случае, если вам нужно что-то быстрее: . Обратите внимание, что даже если Object.hashCode будет одинаковым каждый раз, когда он в любом случае слишком короткий (всего 32 бита), чтобы обеспечить высокую уникальность. Я думаю, что 64 бита - это минимум, чтобы вычислить хороший хэш-код. Имейте в виду, что MD5 генерирует хэш-код длиной 128 бит, что в этой ситуации еще больше необходимо.

Конечно, для использования MessageDigest вам необходимо сначала сериализовать (в вашем случае маршалл) объект.

+0

Благодарю всех вас за ответы. Я рассчитываю MD5 из запрошенного запроса. – Alex

5

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

Но если вы описали проблему, которую пытаетесь решить, вы, вероятно, получите более точное решение.

4

Если вы контролируете источник, вы можете реализовать hashCode(), чтобы он был последовательным от одного исполнения к другому.

3

Вы хотите сделать это для все Объекты Java?

В этом случае hashCode() не работает.

Для некоторых классов hashCode() имеет более строгое определение, гарантирующее равенство во всех исполнениях. Например, String имеет четко определенную реализацию hashCode. Аналогично List и Set имеют четко определенные значения при условии, что все объекты, содержащиеся в них также, имеют четко определенные значения (обратите внимание, что общее значение Collection.hashCode()не требует, чтобы значение было четко определено).

Для других классов вам нужно будет использовать отражение рекурсивно с определенной четко выраженной формулой для построения контрольной суммы.

2

Hashcode в порядке. Либо данный класс переопределяет equals, а также, как требует контракт, hashcode. По контракту, если equals возвращает true hashcode должен быть таким же.
Или класс не переопределяет equals. В этом случае разные исполнения вашего приложения не могут создать тот же объект, поэтому проблем нет.
Единственная проблема заключается в том, что некоторые классы (даже из Java API) разорвать контракт на equals.

2

Библиотека Apache commons lang предоставляет класс HashCodeBuilder, который помогает создавать хеш-код, который удовлетворяет вашим требованиям из свойств класса.

Пример:

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

См Commons Lang API

2

Если вы е вы используете Eclipse IDE, то он имеет действие (в меню Source) для создания хэша-кода и равна функция. Он позволяет вам выбирать атрибуты класса, который вы хотите в хэш-коде. Это похоже на использование ранее предложенного метода HashCodeBuilder.

Вы также можете передать объект в массив байтов и сгенерировать MD5.

8

Пример

 
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. Object -> String (например, GSON - вы не должны писать сериализации не перечислить все поля вашего класса)

  2. Строка .hashCode() -> int (вместо Object.hashCode()! Эта реализация hashCode() зависит от содержимого String, а не от адреса в памяти - вы можете использовать его в разных запусках приложений, разных потоках и т. д.)

(или 2. String -> md5)

Смежные вопросы