2012-03-19 4 views
6

Мне интересно, если по умолчанию реализация Java Hashtable#hashCode() нарушена, когда Hashtable содержит только записи с одинаковыми ключами и значениями на пару.Ошибка реализации Java Hashtable # hashCode()?

См, например, следующее заявление:

public class HashtableHash { 
    public static void main(final String[] args) { 
     final Hashtable<String, String> ht = new Hashtable<String, String>(); 

     final int h1 = ht.hashCode(); 
     System.out.println(h1); // output is 0 

     ht.put("Test", "Test"); 

     final int h2 = ht.hashCode(); 
     System.out.println(h2); // output is 0 ?!? 

     // Hashtable#hashCode() uses this algorithm to calculate hash code 
     // of every element: 
     // 
     // h += e.key.hashCode()^e.value.hashCode() 
     // 
     // The result of XOR on identical hash codes is always 0 
     // (because all bits are equal) 

     ht.put("Test2", "Hello world"); 

     final int h3 = ht.hashCode(); 
     System.out.println(h3); // output is some hash code 
    } 
} 

хэш-код для пустого Hashtable равно 0. После того, как запись с ключом "Test" и значением "Test" было добавлено в Hastable хэш-код еще 0.

проблема в том, что в методе hashCode() в hashTable в хэш-код каждой записи рассчитывается и добавляется в хэш-код следующим

h += e.key.hashCode()^e.value.hashCode() 

Однако XOR на идентичных хеш-кодах (что соответствует идентичным строкам) всегда равно 0. Таким образом, записи с идентичными ключами и значениями не являются частью хэш-кода Hashtable.

Эта реализация является imho сломанной, потому что Hashtable фактически изменился. Не имеет значения, совпадают ли ключ и значение.

+2

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

+2

Вы * не можете * полагаться на другой хэш-код только потому, что объект отличается. Не могли бы вы сказать, что hashCode также сломан, если я добавлю два совершенно разных объекта, а hashCode тоже останется прежним? В этом случае всякая реализация хэш-кода нарушается, если вселенная возможных объектов больше 2^32. – Voo

+0

Это скорее наблюдение, чем вопрос. (Хотя не мой downvote.) –

ответ

6

Из документации по hashCode;

Это не требуется, если два объекта неравны в соответствии с методом равно (java.lang.Object), то вызов метода HashCode на каждого из двух объектов должны производить различные результаты целочисленные. Однако программист должен помнить, что получение отличных результатов для неравных объектов может повысить производительность hashtables.

Другими словами, плохая реализация - возможно. Сломанный - не по спецификации.

5

Это не сломанный, он работает как разработанный и рекламируемый. Хэш-код двух равных Map s не равен двум равным Map.

1

Единственным требованием hashCode является то, что если два объекта равны, то их хэш-коды должны быть равны. Таким образом,

public int hashCode() { 
    return 123; 
} 

совершенно применимо, хотя и не оптимально.

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