2016-04-12 64 views
11

Voglio solo introdurre un modello di osservatore piccolo (ascoltatori) in una delle mie classi e voglio utilizzare l'approccio delle migliori pratiche.Corretto (e migliore) tipo di raccolta per gli ascoltatori in Java

mia interfaccia ascoltatore:

public interface ExpansionListener { 
    void expanded(); 
    void collapsed(); 
} 

Pertanto, voglio tenere un elenco di ascoltatori

private List listener; // What kind of list should I take? 

e due metodi addListener(ExpansionListener l) e removeListener(ExpansionListener l).

Ora, la mia domanda: Che tipo di elenco dovrei prendere? Ho pensato di utilizzare una lista concorrente come CopyOnWriteArrayList, ma ho scoperto che esiste anche EventListenerList. Qual è l'approccio best-practice per listener-lists in Java?

+0

eventListenerList sembra essere un buon candidato – Sanjeev

+2

userei un 'List ' per cominciare, se si desidera solo per permettere quel tipo di ascoltatore. Quindi probabilmente andrei con 'CopyOnWriteArrayList' dato che le modifiche agli ascoltatori sono probabilmente poco frequenti, ma le scritture potrebbero verificarsi in parallelo da più thread (solo ipotesi sulla tua architettura). – Thomas

+0

Un 'Set' sarà più appropriato per impedire a un oggetto di avere più listener dello stesso tipo. – Titus

risposta

9

Il CopyOnWriteArrayList è sicuro da discussioni. Non tutti i componenti Swing sono thread-safe.

Nota: prima di Java 8, l'iterazione su questa raccolta creava garbage, tuttavia in Java 8 lo Iterator può essere inserito nello stack con Escape Analysis.

final List<EventListener> listeners = new CopyOnWriteArrayList<>(); 

if (!listeners.contains(listener)) 
    listeners.add(listener); 

utilizzando un set sarebbe preferibile esp come si potrebbe desiderare di ignorare le registrazioni duplicate di un ascoltatore in modo sicuro thread.

final Set<EventListener> listeners = new CopyOnWriteArraySet<>(); 

listeners.add(listener); 

La performance sarà più o meno lo stesso, anche se la CopyOnWriteArraySet ha il vantaggio che il add è atomico, dove, come fare contains e poi add non è atomica.

MODIFICA: Come suggerisce @Hulk, è possibile utilizzare CopyOnWriteArrayList.addIfAbsent, tuttavia questo metodo non è disponibile in Elenco.

final CopyOnWriteArrayList<EventListener> listeners = new CopyOnWriteArrayList<>(); 

listeners.addIfAbsent(listener); 
+0

@Hulk sarebbe per 'CopyOnWriteArrayList' anche se non è disponibile su' Elenco' –