views:

87

answers:

4

Is there a method in JDK or apache commons to "pop" a list of elements from a java.util.List? I mean, remove the list of elements and return it, like this method:

public Collection pop(Collection elementsToPop, Collection elements) {

  Collection popped = new ArrayList();

  for (Object object : elementsToPop) {
    if (elements.contains(object)) {
      elements.remove(object);
      popped.add(object);
    }
  }

  return popped;
}
+3  A: 

If you're looking for a stack-like structure I suggest accepting a Deque (LinkedList is the most common implementation) instead of a Collection.

If you don't actually need to treat it as a stack, just get an iterator from the Collection and use the remove() method:

for (Iterator<SomeType> it = elements.iterator(); it.hasNext(); ) {
    SomeType e = it.next();
    it.remove();
    popped.add(e);
}

Do note that remove is an optional operation, and some implementations may throw an UnsupportedOperationException (for example, the iterator returned by a Collection from Collections.unmodifiable...() will).

Edit: After looking more closely at your question, I think you just need this:

elements.removeAll(elementsToRemove);

If your main point is you need to know exactly which elements were actually popped, I think you're stuck with your original code.

Mark Peters
Actually, it appears I didn't read closely enough. You have a very non-standard definition of "pop" that mislead me to post this answer. More applicable answer coming.
Mark Peters
I know "pop" was not the best word to use, so I gave an example of what I wanted. But looks like there's no method like this implemented for JDK or apache commons, so, by now, will continue with my own, and I will use your Iterator hint, thanks!
Tom Brito
+1  A: 

I guess no, because you definition of 'pop' operation is highly non-standard. Usually it takes no arguments (except collection itself) and returns and removes the top-most one.

But once you noted apache commons, this would achieve the same effect as your code.

Collection result = CollectionUtils.intersection(a, b);
a.removeAll(b);

edit
http://commons.apache.org/collections/api-release/index.html

Nikita Rybak
A: 

There isn't a method exactly like what you are asking for, but it looks like you are already pretty close with your code.

Some suggestions:

  • Consider using removeAll(object) instead of remove(object) if elements is an arbitrary collection since you may need to remove duplicates e.g. if elements is a list.

  • contains() is slow for some collection types (e.g. lists) since it needs to traverse the entire data structure. Given that this is in your inner loop you are at risk of O(n^2) performance issues. If you can make the algorithm work with a HashSet or HashMap then contains() will by O(1) and your algorithm will be much more efficient.

mikera
+1  A: 

There is no such method in the standard JDK-provided methods. Apache Commons provides the ListUtils.subtract() method.

Edit: As other answerers have noted, your use of the term pop is nonstandard. Usually,

The pop operation removes an item from the top of [a stack]

Wikipedia has a nice description of stacks.

Lord Torgamus
+1 for subtract; removeAll doesn't respect cardinality like the poster's snippet does. But this doesn't get you a list of elements that were actually removed like his does.
Mark Peters
@Mark, hm, you're right; I read the description but not the source, and misunderstood. +1, I will keep looking.
Lord Torgamus