2014-01-27 4 views
1

У меня есть класс, который является Set и I переопределяет .equals(), чтобы проверить, являются ли наборы равными по элементам. Как переопределить Hashcode так от того, что я видел, есть некоторая взаимосвязь между этими двумяПереопределение HashCode

public class ASet{ 
Set g=new Set(); 


public boolean equals(Object s1) 
{ 
    Set S= (Set)s1; 
    for(Object o : S.getcontents()) 
    { 
     for(Object r : g.getcontents()) 
     { 
      if(!o.equals(r)) 
      { 
       return false; 
      } 
     } 
    } 
    return true; 
} 

public int hashCode() { 
     ????????? 
} 
+0

Если вы не хотите помещать этот набор в другой HasSet или HashMap, вам не нужно переопределять hashCode. – TwilightSun

+0

Почему вы завертываете Set? –

+0

@ TwilightSun.I не будет. Это хорошо знать! Если бы я сделал, как бы я переопределить его? – user3236409

ответ

2

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

Вы должны сделать два итератора и объединить их в одном цикле. Теперь вы можете сравнить элементы, возвращаемые первым итератором, с элементами, возвращаемыми вторым итератором, и вернуть false, если они не совпадают.

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

public int hashCode() { 
    int res = 0; 
    for(Object r : g.getcontents()) { 
     res += r.hashCode(); 
    } 
    return res; 
} 

Однако, это не самый лучший хэш-код, который вы могли бы сделать, потому что два набора с различным порядком будут иметь один и тот же хэш-код. Лучший подход заключается в умножении предыдущее значение по простому числу (31 является типичным примером) перед добавлением следующего хэш-код к ней, как это:

public int hashCode() { 
    int res = 0; 
    for(Object r : g.getcontents()) { 
     res = 31 * res + r.hashCode(); 
    } 
    return res; 
} 

Наконец, записочку о коллекциях и их хэш-кодов : основная цель переопределения хеш-кода состоит в том, чтобы вы могли использовать свой объект в качестве ключа в хэш-коллекции (хеш-набор или хэш-карта). Тем не менее, вы должны быть предельно осторожны с использованием изменяемых объектов, таких как наборы и списки, в качестве ключей в картах или наборах, поскольку мутация ключа, который был помещен в контейнер, уже поставит под угрозу структурную целостность вашего контейнера на основе хэша.

+0

он не реализует Set на самом деле, он просто обертывает его, зачем ему переписывать equals() –

+0

Если я использую стандартную .equals() реализации Set, например TreeSet, о том, есть ли у меня 2 разных ASet Экземпляры, содержащие объекты (с одинаковыми значениями полей) в качестве элементов. Будут ли они считаться равными при сравнении их элементов? – user3236409

+0

@JigarJoshi Единственная причина, по которой вы можете это сделать, - это упражнение. Возможно, план состоит в том, чтобы добавить больше членов, кроме 'Set', или реализовать собственный набор. – dasblinkenlight

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