Java LinkedHashSet从末尾删除一些元素

时间:2013-04-08 22:36:05

标签: java removeall linkedhashset

我正在解决一个问题,我需要存储具有无复制和维护顺序要求的元素。我选择LinkedHashSet,因为它满足了我的要求。

假设我有这段代码:

 LinkedHashSet hs = new LinkedHashSet();
  hs.add("B");
  hs.add("A");
  hs.add("D");
  hs.add("E");
  hs.add("C");
  hs.add("F");
  if(hs.contains("D")){
       //do something to remove elements added after"D" i-e remove "E", "C" and "F"
       //maybe hs.removeAll(Collection<?>c) ??
   }

有人可以指导我删除这些元素的逻辑吗?

我使用错误的数据结构吗?如果是这样,那么什么是更好的选择呢?

4 个答案:

答案 0 :(得分:3)

如果您使用LinkedHashSet,我认为您可能需要使用迭代器来执行删除操作。也就是说找到元素,然后继续移除直到你到达尾部。这将是O(n),但即使您编写了自己的LinkedHashSet(具有双向链接列表和哈希集),您也可以访问原始链接结构,以便您可以在O(1)中剪切链接列表,但是仍然需要从HashSet中删除刚刚从链表中剪切的所有元素,这是O(n)成本再次出现的地方。

总而言之,删除元素,然后保持该元素的迭代器并继续向下移除元素,直到结束。我不确定LinkedHashSet是否公开了所需的调用,但你可能会想出来。

答案 1 :(得分:0)

这里的基本问题是你必须维护两个数据结构,一个代表键/值映射的“map”和另一个代表插入顺序的“list”。

有“map”和“list”组织可以在给定点之后快速删除元素;例如有序树和各种类型的数组以及基于链的列表(以模块定位点的成本为模。)

但是,似乎不可能从两个数据结构中删除N个元素,而不是O(N)。您必须访问要删除的所有元素才能从第二个数据结构中删除它们。 (事实上​​,我怀疑有人可以用数学证明这一点......)

简而言之,没有比目前使用的数据结构更复杂的数据结构。

可以提高性能的区域(使用自定义集合类!)是避免显式使用迭代器。使用迭代器和标准迭代器API,数据结构中元素总数的成本为O(N)。您可以对删除的元素数量进行此O(N) ...如果散列条目节点还具有该序列的next / prev链接。

答案 2 :(得分:0)

您可以通过覆盖add()addAll()来编写自己的ArrayList版本,该版本不允许重复。据我所知,没有“共同”的第三方版本,这一直让我感到惊讶。谁知道一个?

然后删除代码非常简单(不需要使用ListIterator

int idx = this.indexOf("D");
if (idx >= 0) {
  for (int goInReverse = this.size()-1; goInReverse > idx; goInReverse--)
    this.remove(goInReverse);
}

但是,这仍然是O(N),因为你循环遍历List的每个元素。

答案 3 :(得分:0)

因此,在尝试了上面提到的几件事之后,我选择实现不同的数据结构。因为我对这个问题的O(n)没有任何问题(因为我的数据非常小)

我使用了Graphs,这个库非常方便:http://jgrapht.org/

我正在做的是将所有元素作为顶点添加到DirectedGraph,同时在它们之间创建边缘(边缘也帮助我解决了另一个非相关问题)。当删除元素的时候,我使用带有以下伪代码的递归函数:

removeElements(element) {

tempEdge = graph.getOutgoingEdgeFrom(element)
if(tempEdge !=null)
   return;
tempVertex = graph.getTargetVertex(tempEdge)
removeElements(tempVertex)
graph.remove(tempVertex)

}

我同意图DS对这类问题并不好,但在我的条件下,这完全有效......干杯!