Kiedy tworzysz swój własny obiekt pary kluczy, powinieneś zmierzyć się z kilkoma rzeczami.
Po pierwsze, powinieneś być świadomy implementacji hashCode()i equals(). Będziesz musiał to zrobić.
Po drugie, podczas wdrażania hashCode()upewnij się, że rozumiesz, jak to działa. Podany przykład użytkownika
public int hashCode() {
return this.x ^ this.y;
}
jest właściwie jedną z najgorszych implementacji, jakie możesz zrobić. Powód jest prosty: masz dużo równych haszów! A hashCode()powinien zwrócić wartości int, które mają tendencję do być rzadki, wyjątkowy w najlepszym. Użyj czegoś takiego:
public int hashCode() {
return (X << 16) + Y;
}
Jest to szybkie i zwraca unikalne skróty dla kluczy od -2 ^ 16 do 2 ^ 16-1 (od -65536 do 65535). Pasuje to prawie do każdego przypadku. Bardzo rzadko jesteś poza tym zakresem.
Po trzecie, podczas implementacji equals()wiedz również, do czego służy i bądź świadomy tego, jak tworzysz klucze, ponieważ są one obiektami. Często robisz to niepotrzebnie, jeśli stwierdzenia powodują, że zawsze będziesz miał ten sam rezultat.
Jeśli utworzysz klucze w ten sposób: map.put(new Key(x,y),V);nigdy nie będziesz porównywać referencji swoich kluczy. Ponieważ za każdym razem, gdy chcesz uzyskać dostęp do mapy, zrobisz coś takiego map.get(new Key(x,y));. Dlatego equals()nie potrzebujesz takiego oświadczenia if (this == obj). To się nigdy nie wydarzy.
Zamiast if (getClass() != obj.getClass())w equals()lepszym użyciu if (!(obj instanceof this)). Będzie obowiązywać nawet dla podklas.
Więc jedyne, co musisz porównać, to w rzeczywistości X i Y. Więc najlepsza equals()implementacja w tym przypadku to:
public boolean equals (final Object O) {
if (!(O instanceof Key)) return false;
if (((Key) O).X != X) return false;
if (((Key) O).Y != Y) return false;
return true;
}
Ostatecznie twoja kluczowa klasa wygląda tak:
public class Key {
public final int X;
public final int Y;
public Key(final int X, final int Y) {
this.X = X;
this.Y = Y;
}
public boolean equals (final Object O) {
if (!(O instanceof Key)) return false;
if (((Key) O).X != X) return false;
if (((Key) O).Y != Y) return false;
return true;
}
public int hashCode() {
return (X << 16) + Y;
}
}
Możesz podać swoje indeksy wymiarów Xi Ypoziom dostępu publicznego, ponieważ są one ostateczne i nie zawierają poufnych informacji. Nie jestem w 100% pewien, czy privatepoziom dostępu działa poprawnie w każdym przypadku podczas przesyłania Objectdo pliku Key.
Jeśli zastanawiasz się nad finałami, deklaruję wszystko jako ostateczne, którego wartość jest ustawiona na instancji i nigdy się nie zmienia - i dlatego jest stałą obiektową.