Usuwanie elementu podczas iterowania po kolekcji

0

Witajcie,

Mam pytanie - czy taka konstrukcja jest bezpieczna ?


ArrayList<Bla> blablacze;

// uzupelnianie kolekcji, itp

for (Bla temp : blablacze) {
  if (temp.chceBycUsuniety()) {
    blablacze.remove(temp);
  } else {
    // cos...
  }
}

I nie chodzi mi tu jedynie o ArrayList, ale ogolnie o kolekcje w Javie (w tym rowniez ArrayList ;p).

0

Tak, jest bezpieczne. Czemu miałoby nie być?

0

Bezpieczne to jest o ile do listy i obiektów w niej zawartych nie ma dostępu kilka wątków.

0

Ta konstrukcja od razu prowadzi do wyjatku ConcurrentModificationException. I nie znaczy on wcale, ze inny watek modyfikuje kolekcje, podczas gdy inny ja iteruje, ale ze po utworzeniu iteratora kolekcja sie zmienila a iterator dalej jest uzywany.

0

@up możliwe, ale wydaje mi się ze nie będzie problemu bo usuwamy obiekty już obsłużone tym iteratorem.

Tak czy siak można uniknąć problemu tworząc nową kolekcję do której dodajesz te elementy "do usunięcia" a następnie odpalasz metodę usuwającą elementy z kolekcji wyjściowej które są również w tej nowej kolekcji ;)

0

No to w koncu robic tak, jak pokazalem, czy np tworzyc sobie tymczasowa kolekcje elementow do usuniecia i po przeiterowaniu pierwotnej kolekcji dopiero je z niej usunac ? Czy moze jeszcze jakies inne pomysly ?

@up zasugeruje sie tym, ze miales taki sam pomysl, jak ja i tak zrobie ;)

Dzieki.

0

Uzyj jawnego iteratora


		for(Iterator<Bla> it = blablacze.iterator(); it.hasNext(); )
		{
			Bla temp = it.next();
			
			if(temp.chceBycUsuniety())
			{
				it.remove();
			}
			else
			{
				// cos...
			}
		}
0

Nie mozna tak robic, jak juz ktos wspomnial dostaniesz ConcurrentModificationException. Polega to na tym ze kazda kolekcja posiada w sobie liczbe integer ktora jest zwiekszana o 1 w razie zmiany w kolekcji, np metoda add, remove itp. Jak tworzysz iterator, to jest on tworzony z ta liczba. W metodzie next lub hasNext jast sprawdzane czy liczba ta w kolekcji jest rowna liczbie w iteratorze. Jesli podczas iterowania cos usuniesz, to podczas nastepnej iteracji dostaniesz taki wlasnie piekny wyjatek. Aby usuwac, Iterator ma metode remove(), i tego powinienes sie trzymac.

0

mea culpa, byłem początkowo przekonany że autor używa tutaj iterator.remove() ;)
I to jest najlepsze rozwiązanie.

0

Ok. Zastosuje zatem wersje z jawnym iteratorem.

Dziekuje Wam :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1