11

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;
}
The Student
  • 27,520
  • 68
  • 161
  • 264
  • 2
    Do note that you can test the result of remove() and skip the contains check in your code. – Mark Peters Jun 08 '10 at 15:52
  • 1
    You may also want to look into [generics](http://java.sun.com/docs/books/tutorial/java/generics/index.html) for working with collections. – Pops Jun 08 '10 at 16:14

5 Answers5

12

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
  • 80,126
  • 17
  • 159
  • 190
  • 1
    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 Jun 08 '10 at 15:47
  • 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! – The Student Jun 08 '10 at 16:00
2

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.

Pops
  • 30,199
  • 37
  • 136
  • 151
  • 1
    +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 Jun 08 '10 at 15:55
  • @Mark, hm, you're right; I read the description but not the source, and misunderstood. +1, I will keep looking. – Pops Jun 08 '10 at 16:09
1

Linked List provides the functionality as you require, provides a push and pop method.

Refer to the documentation as provided:

Jav_Rock
  • 22,059
  • 20
  • 123
  • 164
1

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
  • 67,365
  • 22
  • 157
  • 181
0

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
  • 105,238
  • 25
  • 256
  • 415