2012-04-25 27 views
7

Szukam struktury danych java podobnej do ArrayList, że kiedy robię dodawanie lub wypychanie z tylko argumentem wartości, indeks będzie zwracany automatycznie.ArrayList z zwróconym indeksem na wartość dodaną

Na przykład:

ArrayList<String> elements = new ArrayList<String>(); 

String element = "foo"; 
String elementTwo = "bar"; 

int index1 = elements.add(element); //note this does not exist, i.e. returns bool in api 
int index2 = elements.add(elementTwo); 

System.out.println(elements.get(index1)); //would give "foo" 

Widziałam napisanie klasy otoki wokół ArrayList, który zarządza licznik, który jest zwiększany przy każdym dodać operacja i Wywoływanie:

ArrayList.add(int index, E element) 

Czy naprawdę trzeba pisać opakowanie dla ArrayList? To wydaje się być czymś tak prostym, że można je gdzieś wyskoczyć z pudełka?

Edit:

muszę indeksu (klucza), który zostanie ustalony i unikalną dla tej usecase. Zaproponowano mapę i zgadzam się z tym. Czy ktoś wie o implementacji mapy, która daje automatycznie (unikalnie) wygenerowany klucz na wstawieniu wartości? Po prostu próbuję zdecydować, czy muszę zaimplementować moje własne opakowanie.

+2

'int index1 = elements.add (element) .size() - 1'; czy to nie zadziała – keety

+1

Co jest nie tak z 'int index1 = elements.size(); elements.add (element); '? – dasblinkenlight

+1

Jestem zdziwiony. Dlaczego tak źle napisać drugą linię, aby uzyskać aktualną długość ??? – paulsm4

Odpowiedz

5

Element zostanie dodany na końcu listy. Więc możesz użyć elements.size()-1, aby uzyskać indeks nowych elementów.

Należy pamiętać, że nie będzie działać poprawnie, jeśli wiele wątków modyfikuje listę w tym samym czasie.

EDIT: Należy również pamiętać, że nie może być dobrym pomysłem do korzystania z ArrayList s indeks jako unikatowy identyfikator, ponieważ indeks elementy mogą ulec zmianie (na przykład podczas usuwania elementu lub włóż nową kartę korzystając add(int, Object)) . Jeśli jest to problem zależy od tego, co chcesz zrobić z indeksem: jeśli potrzebujesz go tylko przez krótki czas po dodaniu elementu i możesz mieć pewność, że lista nie zostanie zmodyfikowana w międzyczasie, nie ma problemu. W drugim przypadku nawet metoda zwracająca indeks przy wywołaniu add(Object) nie pomogłaby, ponieważ indeks i tak nie zostanie zaktualizowany. Aby temu zapobiec, możesz:

  • Upewnij się, że nigdy nie usuwasz elementów z listy i nigdy nie dodajesz elementów przy użyciu add(int, Object).
  • Zamiast usuwać elementy, można również ustawić je na null przy użyciu metody set(int, null). W ten sposób żaden indeks elementów się nie zmieni.
  • Użyj innej struktury danych, takiej jak na przykład mapa z niestandardowym identyfikatorem, takim jak helloannalil, sugeruje w swojej odpowiedzi.

Edytowanie 2: nie znaleźć właściwe, gotowe do użycia realizacji (ale to nie znaczy, nie ma, oczywiście). Zaproponować dobre rozwiązanie, więcej informacji na temat zamierzonego wykorzystania struktury danych jest potrzebna, ale oto kilka pomysłów i wskazówek:

  • Jeśli maksymalna liczba elementów nie jest duża, ArrayList mogą być wykorzystane i indeks elementów reprezentuje identyfikator. Jak wspomniano powyżej, aby usunąć element, można go ustawić na null, aby żadne wskaźniki nie zostały zmienione. Podczas wstawiania pozycje z wartościami null można ponownie wykorzystać.
  • Można również skorzystać z jednej z dwóch metod pokazać w tej odpowiedzi: https://stackoverflow.com/a/8939049/1347968 (słowa kluczowe AtomicLong lub IdentityHashMap)
  • uwagi nie zależeć na „wyjątkowość” z Object.hashCode() lub System.identityHashCode(Object) gdyż nie jest gwarantowana (spróbuj go przez uruchomienie przykładu u dołu Suns/Oracles Bug #6321873).
+0

Dzięki za odpowiedź (+1). Pójdę do sprawdzenia odpowiedzi z bardziej szczegółowymi informacjami na temat implementacji mapy lub jej braku. –

+0

@RyanR. Dodałem kilka pomysłów na wdrożenie i notatek ... – siegi

+0

Lubię badania. Uruchomiłem klasę HashClash. Ciekawe, że tam się łamie niepowtarzalność. Nie mam 10 miliardów prób w moim systemie, ale dobrze wiedzieć. –

2

No to co robię, że przypadki (Kocham ArrayLists) jest zdobycie ostatniego indeksu prosząc o wielkości listy:

String thing = "theThing"; 
List<String> strList = new ArrayList<String>(); 
strList.add(thing); 
int indexOfThing = strList.size() - 1; 

To znaczy, jest łatwiejsze niż zaimplementować własną listę i po prostu działa.

2

jeśli naprawdę chcesz tę funkcję, można użyć mapę, ale nie listy

2

oparciu o komentarze i edytować pytanie myślę, że można przedłużyć HashMap do użytku tak:

public class MyMap<V> extends HashMap<Integer, V> { 
    private static final long serialVersionUID = 1L; 
    public int add(V elem) { 
     int key = System.identityHashCode(elem); 
     super.put(key, elem); 
     return key; 
    } 
} 

Następnie wewnątrz swojej klasie deklarują MyMap tak:

private MyMap<String> map = new MyMap<String>(); 

A następnie dodać elementy do MyMap tak:

..... 
..... 
String element = "foo"; 
String elementTwo = "bar"; 
int index1 = map.add(element); 
int index2 = map.add(elementTwo); 

Teraz masz index1 i index2 jako indeksy Włożono sznurki, które można wykorzystać lub przekazywaniu przez cały okres aplikacji. można wstawiać lub usuwać elementy w MyMap tyle razy chcesz, ale swoje indeksy (index1 i index2) będzie oddać swoje wstawione elementy tak:

String elem1 = map.get(index1); // will return "foo" 
String elem2 = map.get(index2); // will return "bar" 
+1

Dobra odpowiedź (+1), to jest częścią "wdrożenia mojego własnego opakowania" części mojego pytania. Trochę wstrzyma się z czekiem, ale ostatecznie da ci je, jeśli nikt inny nie będzie w stanie zaproponować bardziej "std library approach". Ciekawe, czy jest to najskuteczniejszy sposób na zrobienie tego? Może lepiej napisać coś takiego na tablicy o stałym rozmiarze, jeśli wiesz, że masz ograniczony zestaw elementów? –

+0

Tak, faktycznie, jest to objęte częścią "wdrożenia mojego własnego opakowania". IMO używające dowolnej tablicy lub implementacji opartej na Kolekcji będzie wymagało dużo więcej kodu, aby działało, ponieważ będziesz dodawać/usuwać elementy z tego magazynu. – anubhava

+0

@RyanR. Należy zauważyć, że nie ma gwarancji, że działa, zgodnie z Javadocs z ['System.identityHashCode (Object)'] (http://docs.oracle.com/javase/7/docs/api/java/lang/System. html) i ['Object.hashCode()'] (http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html) JVM nie musi zwracać oddzielnych kodów skrótów dla różne obiekty. Implementacja zależy od tego, jak chcesz pracować ze strukturą danych: jak często dodajesz, usuwasz lub pobierasz z niej elementy, ile elementów będzie w nim ... Zaktualizuję później odpowiedź, ale pomogłoby, gdybyś podał więcej information ... :-) – siegi

0
String thing = "theThing"; 
List<String> strList = new ArrayList<String>(); 
strList.add(thing); 
int indexOfThing = strList.size() - 1; 

Jeśli usunąć element, to nie będzie dłuższa praca.

+0

Dowiedz się, jak dodać kod do swoich odpowiedzi; http://stackoverflow.com/tour – krisdyson

Powiązane problemy