La classe Collections

di  Antonio Coschignano, marted́ 27 ottobre 2009
Pagina 2 di 2

Singleton

Per spiegare l'importanza di questo metodo la via più facile è mostrare subito un esempio. Immaginiamo di avere una lista popolata da 1000 numeri con valori casuali che variano da 1 a 10:
List <Integer> lista = new LinkedList<Integer>();
  for(int i = 0; i < 10000; i++) {
    int n = (int)(Math.random()*10)+1;
    lista.add(n);
  }
Ad esempio abbiamo la necessità di eliminare dalla lista tutti le occorrenze uguali a 5. Qual'è il modo più veloce? Cosi ad intuito viene subito da pensare di iterare tutta la lista ed ad ogni occorrenza trovata eliminare l'elemento :
Iterator <Integer> it =  lista.iterator();
while(it.hasNext()) {
    int n = it.next();
    if (n==5) it.remove();
}
Molto più elegantemente e risparmiando righe di codice, possiamo utilizzare il metodo Collections.singleton(T element) che ritorna un oggetto di tipo Set<T> con un solo elemento che è quello passato come parametro :
lista.removeAll(Collections.singleton(5));
Esistono altri due metodi per i contenitori Map e List ma sempre con la stessa funzione:
  • static List singletonList(Object o)
  • static Map singletonMap(Object key, Object value)

Liste immutabili

Una lista è detta immutabile quando non si può effettuare nessuna altra modifica alla lista stessa. Ci sono diversi casi in cui ciò diventa necessario. La classe Collections fornisce un metodo per ogno tipo di contenitore presente nel framework per effettuare questo tipo di modifica:
  • public static Collection unmodifiableCollection(Collection c)
  • public static Set unmodifiableSet(Set s)
  • public static SortedSet unmodifiableSortedSet(SortedSet s)
  • public static List unmodifiableList(List list)
Vediamo un esempio:
....
List l = new LinkedList();
l.add(..)
List list = Collections.unmodifiableList(l);
L' oggetto list in questo caso è accessibile in sola lettura. Se si cerca di aggiungere o rimuovere un elemento viene lanciata una UnsupportedOperationException.

Liste sincronizzate

Sincronizzare una lista significa renderla capace di funzionare correttamente in ambienti multithreading, cioè garantire la consistenza di dati nel caso in cui diversi thread accedono simultanemante alla lista. Le implementazioni di LinkedList, ArrayList, HashMap e tanti altri contenitori non sono thread-safe, non sono sviluppate in modo tale da garantire una consistenza dei dati in casi di programmazione concorrente. La classe Collections per ogni contenitore implementa un metodo che trasforma la nostra struttura dati in una struttura sincronizzata:
  • static Collection synchronizedCollection(Collection c)
  • static List synchronizedList(List list)
  • static Map synchronizedMap(Map m)
  • static Set synchronizedSet(Set s)
  • static SortedMap synchronizedSortedMap(SortedMap m)
  • static SortedSet synchronizedSortedSet(SortedSet s)
Vediamo subito un esempio con un ogetto di tipo List:
List l = new LinkedList();
l.add(..);
List <String> list = Collections.synchronizedList(l);
Se 'immergiamo' l'oggetto list in un contesto multithreading sarà in grado di garantire la consistenza dei dati. Attenzione agli iteratori, in quanto esso non è thread-safe. Se ad esempio dobbiamo iterare la lista dobbiamo comunque utilizzare il blocco synchronized ad esempio continuando il codice che abbiamo scritto sopra dobbiamo procedere in questo modo:
synchronized(list) {
  Iterator <String> it = list.iterator();
  while(it.hasNext()) {
    System.out.println(it.next());
  }
}
Queste due ultime funzionalità che abbiamo visto cioè synchronized ed unmodifiable sono i cosiddetti metodi wrappers della classe Collections. Il metodo in poche parole copia il contentuto della struttura dati che li viene passato nel metodo in un oggetto, che implementa la stessa interfaccia, però con le caratteristiche richieste.
Pagine » 1 2