2009-07-22 10 views
5

Metoda equals() (i w tym przypadku także metoda compareTo()) może stać się hotspotem wydajności (np. W dużym natężeniu ruchu HashMap). Zastanawiałem się, jakie sztuczki ludzie przyjęli, aby zoptymalizować te metody w tych przypadkach, gdy okażą się konieczne.Metoda optymalizacji równań()

IntelliJ IDEA na przykład generuje następujące:

public boolean equals(Object o) { 
    if (this == o) return true; 
    if (o == null || getClass() != o.getClass()) return false; 

    ... 
} 

Co jeszcze można natknąć, które mogą być wskazówką do pisania dobrego wykonywania equals() metody?

Odpowiedz

14

Niektóre ogólne pomysły, które niekoniecznie są specyficzne dla equals()

  • Fail tak wcześnie, jak to możliwe. Podobnie jak w opublikowanym fragmencie, zacznij od najszerszych kryteriów wykluczenia, a następnie stań się bardziej drobnoziarnisty, aby metoda mogła wrócić tak szybko, jak to możliwe.
  • Porównaj tylko atrybuty wymagane dla równości. Czasami widziałem, jak ludzie porównują każdy element informacji dostarczanej przez klasę, mimo że tylko garść atrybutów odgrywa rolę semantyczną dla równości dwóch instancji klasy. To oczywiście zależy od klasy i projektu. Należy unikać rekurencji równości, jeśli to możliwe,
  • . W zależności od rodzaju klasy atrybutów porównywania, można dostać się w sytuacjach, gdy są rekurencyjnie zawijających equals() na siebie lub innych przedmiotów, które mogą mieć ukryty wpływ na wydajność

Oprócz względów wydajności, don” t zapomnieć equals API contract aby upewnić się, że równość jest odruchowy, symetryczny, przechodnia i zgodne i zawsze zastępują hashcode(), jak również, gdy zastępują equals().

5

myślę, że jesteś już na kluczowy element, bo powiedziałeś:

... gdy okaże się to niezbędne.

Pamiętaj ogólne zasady optymalizacji:

  1. Nie
  2. nie ... jeszcze
  3. profilu przed optymalizacji

Słyszałem je w klasa lat temu i tak blisko, jak mogę powiedzieć, jest źródłem.

2

Sprawdź książkę "Skuteczna Java" autorstwa Joshua Blocha. Ma kilka niesamowitych wskazówek i całą sekcję na temat tego pytania. Powodzenia!

1

Możesz wziąć sygnał od string interning.

Jeśli twoje obiekty są niezmienne, możesz zaimplementować własny "interning", używając statycznej metody fabrycznej i umieszczając unikalne instancje w tabeli mieszającej. Jeśli to zrobisz, wtedy gdy odniesienia są równe, obiekty są równe.

+0

Powinienem wspomnieć, że metoda fabryczna rozdzieliłaby tę samą instancję z tabeli mieszającej po wywołaniu z równoważnymi wartościami. – devgeezer

+1

Musisz zachować ostrożność przy "interningu". Może to prowadzić do problemów z wydajnością i wycieków pamięci, jeśli zostanie zrobione źle. Rzeczywiście, dlatego wywołanie String.intern() może być złym pomysłem. –

+0

Są to dobre przestrogi, o których należy pamiętać. Myślę, że moja rada dotycząca optymalizacji polegałaby zazwyczaj na szukaniu gdzie indziej, chyba że posiadasz solidny dowód na to, że Equals (...) zajmuje niedopuszczalnie długi czas. – devgeezer

1

Jeśli twoje obiekty znajdują się w środowisku, w którym masz całkowitą kontrolę nad tym, co wywołuje na nich equals(), powinieneś śledzić, jakiego rodzaju porównań dokonujesz, i odpowiednio dostroić metodę equals().

Możesz być w stanie potwierdzić, że niektóre scenariusze nie stało, więc nie muszą być kodowane w ciągu equals(), takich jak:

  • porównując null
  • porównywaniu różnych rodzajów
  • porównując siebie

Możesz także wybrać odpowiednią kolejność przeprowadzanych kontroli, sprawdzając najczęstsze przyczyny niepowodzenia ul.

0

Proponuję, aby powiększenie HashMap było równe() jest kosztowne (np. Poprzez zmniejszenie współczynnika obciążenia). W ten sposób będziesz miał mniej kolizji i miejmy nadzieję, że jeśli (o == this) return true będzie pasować najczęściej.