Tuesday, October 21, 2014

Ștergerea elementelor unei liste în timpul iterării

Începând cu Java 1.5, avem la dispoziție forma for-each a clasicului ciclu for. Aceasta ne ajută să iterăm rapid o colecție, astfel:

for (String element : list) {
   System.out.println(element);
}

unde variabila list a fost declarată și inițializată astfel:

List<String> list = new ArrayList<>() { {
      add("Luni");
      add("Marti");
      add("Miercuri");
      add("Party");
      add("Joi");
      add("Vineri");
   }
};

ACTUALIZARE: Se pare că varianta aceasta de adăugare a elementelor e un anti-pattern, deci nu e bine să o folosim. Detalii aici:
http://blog.jooq.org/2014/12/08/dont-be-clever-the-double-curly-braces-anti-pattern/

O problemă devenită deja clasică este ștergerea de elemente în timpul iterării. Dacă în interiorul ciclului for scriem ceva de genul:

for (String element : list) {
   if (element.equals("Party")) {
      list.remove(element);
   }
}

se aruncă la runtime o excepție java.util.ConcurrentModificationException.
Nu putem folosi forma for-each a ciclului for pentru a șterge elemente în timpul iterării, dar avem la dispoziție interfața java.util.Iterator, care expune metoda remove(). Aceasta se dovedește a fi exact ce avem nevoie:

for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
   if (iterator.next().equals("Party")) {
      iterator.remove();
   }
}


Metoda remove() șterge ultimul element returnat de metoda next(), declarată în interfața Iterator. Totuși, trebuie să ținem cont de faptul că această operație este opțională, după cum se menționează în Javadoc. În concluzie, atunci când folosim iteratori putem atât să iterăm colecția, cât și să ștergem elementele acesteia.

Monday, October 20, 2014

Adăugarea rapidă a unor elemente într-o listă nouă

Am întâlnit unele situații în care am avut nevoie rapid de o listă (java.util.List) căreia să-i adaug, la fel de rapid, câteva elemente. Primul lucru ce îmi venea în minte era să creez o astfel de listă, căreia să-i adaug apoi, rând pe rând elemente, apelând metoda add() astfel:

List<String> list = new ArrayList<>();
list.add("Luni");
list.add("Marti");
list.add("Miercuri");
list.add("Joi");
list.add("Vineri");

O modalitate destul de enervantă și ineficientă, nu?
La un moment dat însă, am găsit o variantă ceva mai elegantă, care se folosește de clase interne, anonime:

List<String> list = new ArrayList<>() { {
      add("Luni");
      add("Marti");
      add("Miercuri");
      add("Joi");
      add("Vineri");
   }
};

ACTUALIZARE: Se pare că varianta aceasta e un anti-pattern, deci nu e bine să o folosim. Detalii aici:
http://blog.jooq.org/2014/12/08/dont-be-clever-the-double-curly-braces-anti-pattern/

În plus, un coleg de muncă mi-a atras atenția că există o variantă și mai rapidă:

List<String> list = Arrays.asList("Luni", "Marti", "Miercuri", "Joi", "Vineri");

Acest ultim exemplu este discutat pe StackOverflow, la următoarea adresă:


Răspunsul acceptat menționează, de asemenea, și faptul că această modalitate nu permite adăugarea de noi elemente acelei liste, întrucât este ”fixed-size”, după cum spune și documentația: