First you need to consider whether you will delete from the center of the list often compared to the length of the list. If your list has N
items but you delete much less often than 1/N
, don't worry about it. Use LinkedList
or ArrayDeque
as you prefer. (If your lists are occasionally huge and then shrink, but are mostly small, LinkedList
is better as it's easy to recover the memory; otherwise, ArrayDeque
doesn't need extra objects, so it's a bit faster and more compact--except the underlying array never shrinks.)
If, on the other hand, you delete quite a bit more often than 1/N
, then you should consider a LinkedHashSet
, which maintains a linked list queue on top of a hash set--but it is a set, so keep in mind that you can't store duplicate elements. This has the overhead of LinkedList
and ArrayDeque
put together, but if you're doing central deletes often, it'll likely be worth it.
The optimal structure, however--if you really need every last ounce of speed and are willing to spend the coding time to get it--would be a "resizable" array (i.e. reallocated when it was too small) with a circular buffer where you could blank out elements from the middle by setting them to null. (You could also reallocate the buffer when too much was empty if you had a perverse use case then.) I don't advise coding this unless you either really enjoy coding high-performance data structures or have good evidence that this is one of the key bottlenecks in your code and thus you really need it.