Я начну с того, что у вас есть пара требований, которые не имеют смысла вместе. Вы ищете коллекцию, которая удаляет дубликаты и поддерживает слабые ссылки, которые указывают мне, что слушатели могут появляться и исчезать в неопределенное время. Однако вы хотите сохранить порядок вставки и позволить одному слушателю отменить все последующие уведомления. Для меня это звучит как рецепт труднодоступных ошибок, и я настоятельно рекомендую переосмыслить его.
Тем не менее, у вас есть одно требование, которое в значительной степени определяет решение: вам не нужен ConcurrentModificationException
, который может прийти от обычного итератора. Это означает, что вам придется скопировать оригинальный список. По пути вы можете проверить и удалить пустые ссылки:
// the master list
List<WeakReference<MyListener>> _list = new ArrayList<WeakReference<MyListener>>();
// inside your send-notification method
List<MyListener> toNotify = new ArrayList<MyListener>(_list.size());
Iterator<WeakReference<MyListener>> itx = _list.iterator();
while (itx.hasNext())
{
WeakReference<MyListener> ref = itx.next();
MyListener lsnr = ref.get();
if (lsnr != null)
toNotify.add(lsnr);
else
itx.remove();
}
// now iterate "toNotify" and invoke the listeners
Вы, наверное, сейчас беситесь, говоря: «Список! Это линейная структура данных! Я не могу это использовать, вставка - O (N)!»
Ну, да, вы можете. Я не знаю, сколько слушателей вы планируете иметь. Но пока вы <100 (и, скорее всего, <100 000), стоимость линейного поиска для вставки и удаления не будет иметь значения. </p>
Гораздо интереснее с точки зрения кодирования то, как вы справляетесь со слабой ссылкой. Вы заметите, что я явно разыменовываю его в переменную перед проверкой референта на ноль. Это критически важный код при работе со ссылочными объектами: хотя крайне маловероятно, что референт будет собран между двумя вызовами get()
, это возможно.
Что подводит меня к самому WeakReference
. Вам нужно будет создать свой собственный подкласс, который переопределяет методы equals()
и hashCode()
для делегирования его референту. Я думал, что у меня как раз такой класс валяется, но, видимо, нет, так что оставлю это на ваше усмотрение.