Кажется, HashSet не понимает, что два объекта одинаковы.
Я пытаюсь использовать HashSet для хранения объектов созданного мною класса, но, видимо, одни и те же объекты, похоже, имеют два разных хеша, поэтому метод содержимого не понимает, что объект уже находится в HashSet. Это приводит к тому, что моей программе не хватает памяти.
Я не думаю, что я делаю что-то не так, но я все равно хотел получить второе мнение. Я делал подобные операции, до которых все работало нормально, что особенно раздражает. Буду признателен за любую помощь.
Вот мой код
move1 = new Move(t,s);
if(move1.hashCode()==new Move(t,s).hashCode())
System.out.println("match");
move2 = new Move(s,t);
moves.add(move1);
moves.add(move2);
if(moves.contains(new Move(t,s)))
System.out.println("match found");
Вот класс Move:
public class Move {
private int move1;
private int move2;
Move(int m1, int m2)
{
move1 = m1;
move2 = m2;
}
public String toString()
{
return String.valueOf(move1)+" "+String.valueOf(move2);
}
}
Вот вывод, который я получаю
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.HashMap.addEntry(HashMap.java:797)
at java.util.HashMap.put(HashMap.java:431)
at java.util.HashSet.add(HashSet.java:194)
at makeMove.<init>(makeMove.java:33)
3 ответа
Вы должны переопределить Object#hashCode()
метод в Move
класс, чтобы позволить ему вернуть то же самое hashCode()
значение для состояния Move
пример. Не забудьте переопределить Object#equals()
также.
Смотрите также:
Подсказка: если вы используете IDE, например Eclipse, вы также можете просто сгенерировать их. Щелкните правой кнопкой мыши где-нибудь Move
выберите Source > Generate hashCode() и equals (). Вот как это выглядит тогда:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + move1;
result = prime * result + move2;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Move other = (Move) obj;
if (move1 != other.move1)
return false;
if (move2 != other.move2)
return false;
return true;
}
HashSet определит равенство на основе вызова hashCode() и equals(). Вы не реализовали их, поэтому вы унаследуете их от Object. Методы hashCode и equals объекта Object основаны только на том, равны ли ссылки.
Вот почему if(move1.hashCode()==new Move(t,s).hashCode())
ложно Move1 - это экземпляр, отличный от экземпляра, созданного путем вызова new Move(t,s).hashCode().
Вам нужно будет реализовать hashCode и equals в вашем классе Move.
например (хотя, возможно, неоптимально, и вы можете захотеть получить нулевой сейф равный - пусть ваша IDE сгенерирует их, если сможет)
public int hashCode() {
return move1 ^ move2 +;
}
public boolean equals(Object o) {
if(!other instanceof Move)
return false;
Move other = (Move)o;
return other.move1 == move1 && other.move2 == move2;
}
Вы должны переопределить equals() и hasCode()
Это может быть вариантом.
import static java.lang.System.out;
public class Move {
private int move1;
private int move2;
Move(int m1, int m2) {
move1 = m1;
move2 = m2;
}
public String toString() {
return String.valueOf(move1)+" "+String.valueOf(move2);
}
public int hashCode() {
return move1 * 31 + move2 * 31;
}
public boolean equals( Object other ) {
if( this == other ) { return true; }
if( other instanceof Move ) {
Move m2 = ( Move ) other;
return this.move1 == m2.move1 && this.move2 == m2.move2;
}
return false;
}
public static void main( String [] args ) {
out.println( new Move(2,3).equals( new Move(2,3)));
out.println( new Move(1,1).hashCode() == new Move(1,1).hashCode() );
}
}
Вы должны определить, важен ли порядок хода (от 1,2 до 2,1 или нет)
Для дополнительной информации:
Какие проблемы следует учитывать при переопределении equals и hashCode в Java?
Элемент 8: всегда переопределяйте hashCode, когда вы переопределяете равно: "Эффективная Java" http://bit.ly/cd7uUl