3

Is there a more elegant way in Guava to remove items which meet a certain predicate from a collection and collect these removed items at the same time? See code below for an example.

public static void main(String[] a) { final List<String> list = new LinkedList<String>(); list.add("..."); ... final List<String> removedItems = new LinkedList<String>(); Iterables.removeIf(list, new Predicate<String>() { public boolean apply(final String o) { if (...) { // some condition removedItems.add(o); return true; } return false; } }); System.out.println(removedItems); } 

Thanks!

edit: My question is not about partitioning a list, but about removing elements from a collection and collecting them at the same time. I edited my question to avoid confusion.

5
  • 1
    Related: stackoverflow.com/q/10547631/521799 Commented Aug 12, 2014 at 17:35
  • My question is not about partitioning a list, but about removing elements from a collection and collecting them at the same time. I edited my question to avoid confusion. Commented Aug 13, 2014 at 6:18
  • I understand. This is why I said "related". Future visitors of this question might be actually looking for a way to partition a list into two lists, which is only subtly different from your approach. Commented Aug 13, 2014 at 6:38
  • Thanks for your comment! I think it was a good idea to point that out. Commented Aug 13, 2014 at 6:42
  • Are my changes sufficient to take this question off hold? Commented Aug 13, 2014 at 7:20

2 Answers 2

1
Predicate<Integer> predicate = new Predicate<>() { public boolean apply(final Integer o) { return o <= 5; } }; List<Integer> removed = Lists.newLinkedList(Iterables.filter(list, predicate)); Iterables.removeIf(list, predicate); 
Sign up to request clarification or add additional context in comments.

2 Comments

This iterates twice of the list, which might be/is suboptimal.
Agreed. It's not more efficient, but it's more elegant (IMO)
0

Collection.add() returns true if the call to add() modifies the collection. So, you can shortcut the if / else branch like this:

Iterables.removeIf(list, new Predicate<Integer>() { public boolean apply(final Integer o) { return o <= 5 && removedItems.add(o); } }); 

With Java 8, this becomes

Iterables.removeIf(list, o -> o <= 5 && removedItems.add(o)); 

... or even (without Guava):

list.removeIf(o -> o <= 5 && removedItems.add(o)); 

Of course, not sure if this will be generally perceived as more readable :-)

Partitioning a collection by a predicate:

This question here deals with the problem from a different angle:

Library method to partition a collection by a predicate

2 Comments

This works, but it's generally preferable to avoid side-effects (such as adding to a collection) in a function such as a Predicate. Better to have the predicate strictly determine the matching elements and let something else handle adding to a collection.
@ColinD: I agree. Yet the question is very subjective already, so I figured that "anything goes"

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.