1

I put together a quick test to illustrate my problem:

@Test
public void testRemovalFromWakLinkedList() {
    Object o1 = new Object();
    Object o2 = new Object();
    assertFalse(o1.equals(o2));

    ArrayList<WeakReference<Object>> list = new ArrayList<>();
    assertTrue(list.isEmpty());

    final WeakReference<Object> wo1 = new WeakReference<>(o1);
    list.add(wo1);
    final WeakReference<Object> wo2 = new WeakReference<>(o2);
    list.add(wo2);
    assertEquals(2, list.size());

    final WeakReference<Object> wo2_2 = new WeakReference<>(o2);
    list.remove(wo2_2);
    assertFalse(wo2.equals(wo2_2));
    assertEquals(1, list.size());
}

The last assert fails because the two instances of the WeakReference to the same object are not the same. Thereby the element cannot be removed from the list.

I am aware of this answer to the problem, which suggests to iterate over the list to identify the element. As the remove operation will be called fairly often this does not seem like the best option (operation is O(N)).

Is there a better alternative to remove the element? Or should I forgo the use of WeakReference and manage the removal of elements from the list myself?

Community
  • 1
  • 1
hotzst
  • 7,238
  • 9
  • 41
  • 64

1 Answers1

1

If you are using java 8 you can code the removal like this:

list.removeIf(wr -> o2.equals(wr.get()));
Thomas Kläger
  • 17,754
  • 3
  • 23
  • 34
  • From the [documentation](https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html#removeIf-java.util.function.Predicate-) I gather however that the implementation is backed by the iterator, so the performance is still O(N). But this is cleaner than to iterate through the list yourself. – hotzst Dec 13 '15 at 08:18
  • Another difference is that removeIf() removes all matching instances whereas remove() only removes the first match. – Thomas Kläger Dec 13 '15 at 08:52
  • The performance of remove() is O(N) too - except for special collections like Set. – Thomas Kläger Dec 13 '15 at 08:53