1212import java .util .Arrays ;
1313import java .util .Collections ;
1414import java .util .List ;
15+ import java .util .Objects ;
1516import java .util .concurrent .Semaphore ;
1617import java .util .concurrent .atomic .AtomicReference ;
1718
18-
1919public class ListenerList {
2020 private static final List <ListenerList > allLists = new ArrayList <>();
2121 private static int maxSize = 0 ;
@@ -100,23 +100,24 @@ public static synchronized void unregisterAll(int id, IEventListener listener) {
100100 private static class ListenerListInst {
101101 private boolean rebuild = true ;
102102 private AtomicReference <IEventListener []> listeners = new AtomicReference <>();
103- private final ArrayList <ArrayList < IEventListener >> priorities ;
103+ private final @ Nullable ArrayList <IEventListener >[] priorities ;
104104 private ListenerListInst parent ;
105105 private List <ListenerListInst > children ;
106106 private final Semaphore writeLock = new Semaphore (1 , true );
107107
108+ @ SuppressWarnings ("unchecked" )
108109 private ListenerListInst () {
109- int count = EventPriority .values ().length ;
110- priorities = new ArrayList <>(count );
111-
112- for (int x = 0 ; x < count ; x ++)
113- priorities .add (new ArrayList <>());
110+ // Make a lazy-loaded array of lists containing listeners for each priority level.
111+ priorities = (ArrayList <IEventListener >[]) new ArrayList [EventPriority .values ().length ];
114112 }
115113
116114 public void dispose () {
117115 writeLock .acquireUninterruptibly ();
118- priorities .forEach (ArrayList ::clear );
119- priorities .clear ();
116+ for (@ Nullable ArrayList <IEventListener > priority : priorities ) {
117+ if (priority != null )
118+ priority .clear ();
119+ }
120+ Arrays .fill (priorities , null );
120121 writeLock .release ();
121122 parent = null ;
122123 listeners = null ;
@@ -141,7 +142,7 @@ private ListenerListInst(ListenerListInst parent) {
141142 */
142143 public ArrayList <IEventListener > getListeners (EventPriority priority ) {
143144 writeLock .acquireUninterruptibly ();
144- ArrayList <IEventListener > ret = new ArrayList <>(priorities . get (priority . ordinal () ));
145+ ArrayList <IEventListener > ret = new ArrayList <>(getListenersForPriority (priority ));
145146 writeLock .release ();
146147 if (parent != null )
147148 ret .addAll (parent .getListeners (priority ));
@@ -193,7 +194,7 @@ private void buildCache() {
193194 ArrayList <IEventListener > ret = new ArrayList <>();
194195 Arrays .stream (EventPriority .values ()).forEach (value -> {
195196 List <IEventListener > listeners = getListeners (value );
196- if (listeners .size () > 0 ) {
197+ if (! listeners .isEmpty () ) {
197198 ret .add (value ); //Add the priority to notify the event of it's current phase.
198199 ret .addAll (listeners );
199200 }
@@ -205,15 +206,26 @@ private void buildCache() {
205206 public void register (EventPriority priority , IEventListener listener ) {
206207 if (listener == null ) return ;
207208 writeLock .acquireUninterruptibly ();
208- priorities . get (priority . ordinal () ).add (listener );
209+ getListenersForPriority (priority ).add (listener );
209210 writeLock .release ();
210211 this .forceRebuild ();
211212 }
212213
213214 public void unregister (IEventListener listener ) {
214215 writeLock .acquireUninterruptibly ();
215- priorities .stream ().filter (list -> list .remove (listener )).forEach (list -> this .forceRebuild ());
216+ Arrays .stream (priorities )
217+ .filter (Objects ::nonNull )
218+ .filter (list -> list .remove (listener ))
219+ .forEach (list -> this .forceRebuild ());
216220 writeLock .release ();
217221 }
222+
223+ private ArrayList <IEventListener > getListenersForPriority (EventPriority priority ) {
224+ var listenersForPriority = priorities [priority .ordinal ()];
225+ if (listenersForPriority == null )
226+ listenersForPriority = priorities [priority .ordinal ()] = new ArrayList <>();
227+
228+ return listenersForPriority ;
229+ }
218230 }
219231}
0 commit comments