如何在Java中从集合中弹出项目?

11

在JDK或apache commons中是否有一种方法可以从java.util.List中“弹出”一系列元素?我的意思是,删除这些元素并将它们返回,就像这个方法:

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;
}

2
请注意,在您的代码中,可以测试remove()的结果并跳过contains检查。 - Mark Peters
1
您可能还想了解泛型,以便更好地处理集合。 - Pops
5个回答

12
如果您正在寻找类似堆栈的结构,我建议接受一个Deque(LinkedList是最常见的实现),而不是一个Collection。
如果您实际上不需要将其视为堆栈,请从Collection获取迭代器并使用remove()方法:
for (Iterator<SomeType> it = elements.iterator(); it.hasNext(); ) {
    SomeType e = it.next();
    it.remove();
    popped.add(e);
}

请注意,remove是一项可选操作,一些实现可能会抛出UnsupportedOperationException异常(例如,由Collections.unmodifiable...()返回的集合迭代器将会抛出此异常)。

编辑:仔细查看您的问题后,我认为您只需要这个:

elements.removeAll(elementsToRemove);

如果您的主要观点是您需要知道确切地哪些元素实际上被弹出,我认为您将坚持使用原始代码。


1
实际上,看起来我没有仔细阅读。你对“pop”的非标准定义误导了我发表这个答案。更适用的答案即将到来。 - Mark Peters
我知道“pop”不是最好的词,所以我举了一个例子来说明我的意思。但看起来JDK或apache commons中没有实现这样的方法,所以现在我将继续使用自己的方法,并使用您的迭代器提示,谢谢! - The Student

2
在标准 JDK 提供的方法中没有这样的方法。Apache Commons 提供了 ListUtils.subtract() 方法
编辑:正如其他回答者所指出的,您使用的术语“pop”是非标准的。通常,

pop 操作从 [堆栈] 顶部移除一个项目

维基百科有一个 关于堆栈的不错描述

1
+1 表示减法;removeAll 不像作者的代码片段一样尊重基数。但是这不能给你一个实际被移除元素的列表。 - Mark Peters
@Mark,嗯,你说得对;我读了描述但没看源代码,误解了。+1,我会继续寻找。 - Pops

1
我认为不行,因为你对“pop”操作的定义非常不标准。通常它不需要任何参数(除了集合本身),并返回并删除最顶部的元素。
但是一旦你提到了Apache Commons,这将实现与你的代码相同的效果。
Collection result = CollectionUtils.intersection(a, b);
a.removeAll(b);

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


1

链表提供了您所需的功能,提供了推入和弹出方法。

请参考提供的文档


0

没有一个像你所要求的方法,但看起来你的代码已经非常接近了。

一些建议:

  • 如果elements是任意集合,则考虑使用removeAll(object)而不是remove(object),因为您可能需要删除重复项,例如如果elements是列表。

  • 对于某些集合类型(例如列表),contains()速度较慢,因为它需要遍历整个数据结构。鉴于这是您的内部循环,您有可能面临O(n^2)性能问题。如果您可以使算法使用HashSet或HashMap工作,则contains()将为O(1),您的算法将更加高效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接