2013-06-24 3 views

Odpowiedz

6

Techniki implementacji tam nie żenią się bardzo dobrze. LinkedHashMap dodaje połączony listing do obiektów wejściowych mapy. IdentityHashMap używa techniki sondowania, dzięki czemu unika się jakichkolwiek obiektów wejściowych.

Istnieje kilka sposobów dodawania właściwości "tożsamości" do kolekcji/mapy.

  • Siła klucz typu zachowywać się poprawnie z finalequals i hashCode metod. Naprawdę wszystkie typy referencyjne powinny to mieć, ale nieważne.
  • Jeśli nie można modyfikować equals i hashCode ale można zmodyfikować klasę, dodać final polu, które jest z final klasy, która posiada final odniesień do rodzaju, że zamierzasz użyć jako klucza. Użyj nowego pola jako klucza.
  • Przechowuj obiekty adapterów w kolekcji/mapie. Będziesz musiał utworzyć nową instancję adaptera dla każdego wyszukiwania. Ma po prostu metody equals/hashCode na wywołanie ==/System.identityHashCode na oryginalnym obiekcie.
+0

czasami wystarczy IdentityHashMap, są przypadki, w których masz * zarówno * normalny HashMap z jakiegoś klienta równości, ale nadal trzeba równość tożsamości relacja w innym kontekście (raz miałem tę sytuację) – kutschkem

0

Można zaimplementować niestandardową mapę, która korzysta z obiektów Wrapper, które używają semantyki tożsamości, i wewnętrznie używać obiektu LinkedHashSet, który korzysta z tych obiektów Wrapper.

3

Jedną z opcji jest użycie LinkedHashSet oraz owijkę

class LinkedIdentityHashSet<E> extends AbstractSet<E> { 
    Set set = new LinkedHashSet(); 

    static class IdentityWrapper { 
     Object obj; 

     IdentityWrapper(Object obj) { 
      this.obj = obj; 
     } 

     public boolean equals(Object obj) { 
      return this.obj == obj; 
     } 

     public int hashCode() { 
      return System.identityHashCode(obj); 
     } 
    } 

    public boolean add(E e) { 
     return set.add(new IdentityWrapper(e)); 
    } 
... 
+1

Metoda equals powinna porównywać 'this.obj' do' ((IdentityWrapper) obj) .obj'. –

+0

Ponieważ ta linia to po prostu sprawdzanie równości odniesienia, rzutowanie nie jest konieczne. Odniesienia będą takie same (lub różne) w środowisku wykonawczym, niezależnie od tego, jakiego typu są w czasie kompilacji. – GreenGiant

+0

Podoba mi się pomysł koncepcyjnie. Wycofane z powodu błędu wspomnianego przez @MikeSamuel. – SlavaSt