Suppose I have a Collection, and a Predicate that matches elements I'd like to remove from the Collection. But I don't just want to discard them, I want to move the matched elements into a new collection. I'd do something like this in Java 7:
List<E> removed = new LinkedList<>(); for (Iterator<E> i = data.iterator(); i.hasNext();) { E e = i.next(); if (predicate.test(e)) { removed.add(e); i.remove(); } } I'm curious if there's a streams / Java 8 way to do it. Collections.removeIf() unfortunately simply returns a boolean (not even a count of the number of removed elements? Too bad.) I envision something like this (though of course .removeAndYield(Predicate) doesn't exist):
List<E> removed = data.removeAndYield(predicate).collect(Collectors.toList()); Note: this question was inspired by a similar question; this question is about the more general case of getting a stream over the items removed from a collection. As pointed out in the linked question, the imperative solution may be more readable, but I'm curious if this is even possible with streams.
Edit: Clearly we can split the task into two separate steps, and assuming the appropriate data structures it will be efficient. The question is can this be done on arbitrary collections (which may not have efficient .contains() etc.).
Setwhile iterating over it without getting aConcurrentModificationException, so any Java 8 way would require at least two iterations as in Misha's answer. AFAIK the only way to do this with a single iteration ofsetis to use an explicitIterator.Iteratorover theCollection, which suggests it's conceptually possible with aStream. Obviously that doesn't mean it's available out of the box, but maybe it's not complicated to do. Or maybe there's a good reason it's not available in the JDK.ArrayList) will scale very badly under iterative solution -- it is expensive to remove elements from the middle of the array via iterator one at a time.