Collections.removeIf spec says nothing whether predicate may refer to collection

Martin Buchholz martinrb at google.com
Mon Sep 24 16:44:29 UTC 2018


We should have specified that the predicate is not permitted to access
the collection at all, (but subclasses may support it).

In practice, we took care during the implementation of the optimized
removeIf methods to preserve invariants so that predicates that only
access the collection for read will still work but pending updates may
not be applied promptly. But I would not like to make that into a
promise.  I can live with a decision either way, as long as the
predicate is forbidden from mutating.

On Mon, Sep 24, 2018 at 12:21 AM, Tagir Valeev <amaembo at gmail.com> wrote:
> Hello!
>
> When using removeIf, sometimes it's tempting to refer to the
> collection from the predicate. E.g.:
>
>     static List<Integer> select(Collection<Integer> input) {
>         List<Integer> result = new LinkedList<>(input);
>         result.removeIf(left -> result.stream().noneMatch(right ->
> right == left * 2));
>         return result;
>     }
>
> Here one may assume that every time the predicate returns true, the
> collection is updated and the subsequent predicate invocations see the
> updated collection. This works for default removeIf implementation,
> but doesn't work for optimized ones like ArrayList, so replacing
> LinkedList with ArrayList in this weird algorithm produces different
> result (e.g. with List.of(1, 4, 2) input). I think that spec should
> explicitly say that intermediate updates are not guaranteed to be
> visible for predicate. What do you think?
>
> With best regards,
> Tagir Valeev


More information about the core-libs-dev mailing list