为什么监听器列表是列表?

2022-09-04 21:47:49

为什么侦听器列表(例如,在Java中使用以及注册和注销侦听器的侦听器)被称为lists,并且通常作为Lists实现?Set不是更合适吗,因为在听众的情况下,有addXxxListener()removeXxxListener()

  • 无论它们以何种顺序被调用(尽管很可能有这样的需求,但它们是特殊情况;普通的侦听器机制没有这样的保证),并且
  • 无需多次注册同一个侦听器(这样做是否会导致调用同一侦听器1次或N次,或者是错误的,是另一个问题)

这仅仅是一个传统问题吗?无论如何,集合都是某种列表。是否存在性能差异?迭代 a 比迭代 ?是占用更多内存还是更少内存?这些差异当然几乎可以忽略不计。ListSet


答案 1

侦听器列表成为列表(而不是集合)的一个重要原因也解释了为什么您经常看到它们被向后迭代。常见方案涉及侦听器在收到某些更改的通知时将自身作为侦听器删除。如果侦听器存储为列表并向前迭代(或存储为一个集合并以某种不确定的顺序迭代),则将自身作为侦听器删除将导致 ConcurrentModificationException。

因此,相反,侦听器存储为列表,并按向后顺序通知。然后,如果侦听器在收到通知时将自己从侦听器列表中删除,则不会导致 ConcurrentModificationException 或移动其他尚未通知的侦听器的索引。


答案 2

什么样的套装?应该所有侦听器都实现 equals 和 hashCode 以便使用哈希集,还是标识哈希集可以使用?将侦听器添加到列表的用例是否值得复杂性增加两倍?有没有一种简单的机制可以使集合安全,以防止在调用其处理程序期间添加或删除侦听器?

可能存在一些性能差异,但肯定有更复杂的设计,它强制将多个添加多个删除决策放入库中,而不是将其留给应用程序。