2010-10-18 14 views
5

Mam ArrayList do przechowywania niektórych danych, ale gdy tylko usunę element z listy, rozmiar nie zmniejsza się, nawet gdy wywołuję ArrayList.trimToSize() . To powoduje mi nullPointerExceptions.Java ArrayList.remove() nie zmniejszając rozmiaru ArrayList

Jak mogę usunąć pojedynczy przedmiot z tablicy ArrayList i odpowiednio zmniejszyć rozmiar listy()?

EDYCJA: W porządku, oto kod. Oto trochę tła, które musisz znać, ponieważ nie mogę opublikować całego kodu. Mam ArrayList nazwie _dataHeap i HashMap nazwie _dataMap. ArrayList jest binarną stertą zawierającą "możliwy do znalezienia" obiekt, który ma klucz. HashMap wiąże się z klucza do indeksu obiektu w tablicy ArrayList. Dzieje się tak dlatego, że przedmiot w kolejce można znaleźć za pomocą elementu z użyciem HashMap lub według indeksu przy użyciu ArrayList. Kluczem może być dowolny obiekt, o ile jest unikalny dla każdego elementu w kolejce.

I debugowałem ten wiersz po linii, a sterty zawiera obiekt, nawet do Hashcode. Problem polega na tym, że obiekt nie jest nigdy usuwany z ArrayList. Musi to oznaczać, że _dataMap.get (element.getKey()) nie wskazuje, gdzie powinien. Sprawdziłem to jednak, użyłem obiektu testowego poza moją implementacją, który mapuje z ciągu do niestandardowego obiektu z ciągiem jako kluczem.

Tworzę jeden obiekt, z napisem "jeden" jako jego klucz. Wstawiam, a następnie próbuję go usunąć. Przeszedłem przez to i wszystko się zgadza, z wyjątkiem jednej rzeczy: Obiekt nigdy nie jest usuwany z kolejki. Ma ten sam Hashcode, ten sam klucz, wszystko. Zostaje usunięty z mapy, ale nie z ArrayList.

Oto metoda remove:

public T remove(T element) { 
    //We'll need this data to return the proper value 
    T t = _dataHeap.get(_dataMap.get(element.getKey())); 
    /* 
    * this Swap() call is used to swap our target with the end 
    * of the arraylist. This means that whenever we remove it, 
    * we don't have a change in indexes of the other nodes. 
    * After that, we downHeapify() to fix the whole graph back 
    * to it's functional state. 
    */ 
    swap(_dataMap.get(element.getKey()),length()-1); 
    //Remove from the Heap 
    _dataHeap.remove(_dataMap.get(element.getKey())); 
    _dataHeap.trimToSize(); 
    //Remove from the Map 
    _dataMap.remove(element.getKey()); 
    downHeapify(); 
    return t; 

Mam nadzieję, że to daje lepsze wyobrażenie o tym, co robię źle.

EDYTUJ DRUGI: Holy crap W końcu to naprawiłem! Wyciągnąłem plik _dataHeap.get (element.index) do własnej zmiennej. To rozwiązało WSZYSTKO!

+0

Czy możesz opublikować kod, którego używasz? – highlycaffeinated

+4

Nie trzeba wywoływać 'trimToSize()', a 'remove()' _should_ poprawnie aktualizuje rozmiar listy. Być może mógłbyś opublikować [SSCCE] (http://sscce.org/), który ilustruje problem? –

Odpowiedz

4

Brzmi dla mnie tak, jakby niczego nie usuwałeś. Jaka jest wartość zwracana z Twojego połączenia remove?

Jeśli używasz remove(int), zwracana wartość powinna mieć wartość inną niż null. Jeśli używasz remove(Object), wynik powinien być prawdziwy. W przeciwnym razie niczego nie usunąłeś. Próba usunięcia elementu, który nie istnieje, nie jest błędem, po prostu zwraca null lub false.

+0

Możesz być na czymś tam. Właśnie sprawdziłem, z drukowaniem ArrayList.contains (element) przed i po usunięciu ... i oba są fałszywe. W jakiś sposób nie jest to dodawanie do prawej listy. – digiholic

+1

Tak naprawdę nie usuwasz niczego. Albo Mike ma rację i zapomniałeś zastąpić 'equals' na niestandardowej klasie, albo obiekt, który próbujesz usunąć, nigdy nie został dodany (lub został już usunięty wcześniej). –

6

Jak powiedział Bemace, sprawdź, czy usunięcie działa tak, jak zamierzałeś. Założę się, że twoja metoda equals() na obiekcie, który komponujesz, nie działa w taki sposób, jak byś tego oczekiwał, ponieważ go nie zastąpiłeś.

Ponadto, po nadpisaniu równych wartości, należy również uwzględnić parametr hashCode. Pozwoli to zaoszczędzić ci pytania, gdy twój obiekt nie działa z HashMaps. :)

Wskazówka: Sprawdź w użyciu JUnit. Wyniesie te małe błędy prosto z wody, dzięki czemu stanie się dla ciebie oczywiste, kiedy coś nie działa, jak masz nadzieję. Bardzo trudno jest zignorować jaskrawoczerwoną plamę na pięknym zielonym pasku.

+3

Re: przesłanianie równań i kodów kresowych, musi przeczytać: http://stackoverflow.com/questions/27581/overriding-equals-and-hashcode-in-java –

+0

OK, zmieniłem tylko równe i Hashcode, ale wciąż jest problem . Nie mogę tego ustalić na czas, więc zamierzam go szybko naprawić, zamiast usunąć, zastąpię go wartością NULL i sprawdzam wartości zerowe przed wykonaniem. – digiholic

+0

Umieść kod. Prawdopodobnie możemy szybko to rozwiązać. – Mike