2013-06-07 2 views
1

У меня есть HashSet, который хранит некоторые грани в графе. Каждый край имеет два узла.HashSet добавляет повторяющиеся объекты

В случае граф неориентированный, добавив, дубликат должен терпеть неудачу:

Edge a = new Edge(new Node("aa"), new Node("bb")); 
Edge duplicate = new Edge(new Node("aa"), new Node("bb")); 

Но в следующем примере это работает:

System.out.println(a.equals(duplicate)); 

Set<Edge> sete = new HashSet<Edge>(); 
System.out.println(sete.contains(a)); 
System.out.println(sete.add(a)); 
System.out.println(sete.contains(duplicate)); 
System.out.println(sete.add(duplicate)); 

Output: 
true 

false 
true 
false 
true 

EDIT: Хорошо, теперь я добавил hashCode метод, который работает для направленных Edges. Помогает ли кто-нибудь мне вычислить хэш для неориентированных границ?

public class Edge { 
    private Node first, second; 

    @Override 
    public /boolean equals(Object ob) { 
     if (ob instanceof Edge) { 
      Edge edge = (Edge) ob; 
      if (first.equals(edge.first) 
        && second.equals(edge.second) 
        || first.equals(edge.second) 
        && second.equals(edge.first)) 
       return true; 
     } 
     return false; 
    } 


    @Override 
    public int hashCode() { 
     int hash = 17; 
     int hashMultiplikator = 79; 
     hash = hashMultiplikator * hash 
       + first.hashCode(); 
     hash = hashMultiplikator * hash 
       + second.hashCode(); 
     return hash; 
    } 
+5

как же вы реализуете равных() и хэш-код()? – Synox

+0

Вы переопределили метод 'equals' для' Node'? – Sam

+0

@Sam '.equals()' недостаточно, вы также должны реализовать '.hashCode()'; иначе вы нарушите контракт «Объект». – fge

ответ

5

Как уже упоминалось в комментариях ...

Вы должны реализовать .equals() и .hashCode() для обоих классов Edge и Node.

A HashSet использует .hashCode() для определения хеш-ведра, в который помещается новая запись; если в этом ковше уже есть записи, он использует .equals() для каждой записи в ведре, чтобы узнать, существует ли запись.

Поскольку вы не переопределить любого из них, реализации этих методов является один из Object:

  • .hashCode() простой хэш над эталонным адресом объекта;
  • .equals() является истинным тогда и только тогда, когда оба объекта являются одной и той же ссылкой (то есть o1 == o2).

И это явно не то, что вы хотите!

1

Единственное объяснение этого феномена - Edge.hashCode неверно или не переопределено. Вы должны добавили эти строки в код

System.out.println(a.hashCode()); 
System.out.println(duplicate.hashCode()); 

знать, почему

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