Java 中侦听器的正确(和最佳)集合类型

我只想在我的一个班级中引入一个小的观察者模式(听众),我想使用最佳实践方法。

我的监听器接口:

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

因此,我想保留一个侦听器列表

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

和 两种方法和.addListener(ExpansionListener l)removeListener(ExpansionListener l)

现在,我的问题是:我应该选择什么样的列表?我考虑过使用像CopyOnWriteArrayList这样的并发列表,但我发现EventListenerList也存在。Java 中侦听器列表的最佳实践方法是什么?


答案 1

是线程安全的。并非所有 Swing 组件都是线程安全的。CopyOnWriteArrayList

注意:在Java 8之前,迭代此集合会产生垃圾,但是在Java 8中,可以使用转义分析将其放在堆栈上。Iterator

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

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

使用 Set 更可取,因为您可能希望以线程安全的方式忽略侦听器的重复注册。

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

listeners.add(listener);

性能将大致相同,尽管其优点是原子的,其中作为做,然后不是原子的。CopyOnWriteArraySetaddcontainsadd

编辑:正如@Hulk建议的那样,您可以使用CopyOnWriteArrayList.addIfAbsent,但是此方法在List上不可用。

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

listeners.addIfAbsent(listener);

答案 2

推荐