快速迭代集合并删除符合特定条件的项目

时间:2013-01-11 19:27:38

标签: java performance data-structures collections

所以我有一个包含Set中的一堆记录的程序。该集可能有几个项目或可能有数十万个。每条记录的一位数据是时间戳。我需要消除一组中的所有项目,但是相互之间的时间间隔为15秒。最有效的方法是什么?

目前我创建了该集的副本。然后我遍历集合,将第一个项目与其他项目进行比较,然后重复。如果发现匹配在15秒内,我将从重复集中删除它。然后将副本集写出到文件中。

显然这有效,但我终于意识到这是非常低效的。对于大型套装,这似乎需要花费很长时间,假设它不是出现其他问题。有人能为我提供更智能,更快捷,更有效(或恰当)的方式来实现这一点吗?我意识到,因为记录包含时间戳,排序它们可能会有很大帮助。我想保留这一切都包含在程序中,所以我想我需要研究排序和比较器。

我无法完全解决问题。我想出了一些改进我的代码的其他想法,但我不禁感到我仍然完全错了。感谢您的任何建议。

哦,这是为了工作,而不是学校或其他什么,所以感谢任何帮助。

4 个答案:

答案 0 :(得分:5)

目前,您所描述的算法在 O(n 2 时间运行。

现在,如果您需要更快的算法,您可以做的是

  • 对您的收藏进行排序(如果java没有基类排序功能,我会感到惊讶) O(n * lg(n))
  • 彼此之间15秒内的所有“匹配”将紧挨着彼此
  • 只需检查相邻元素 O(n)
  • ,您只需迭代每个元素

如果你这样做,那么你的算法可以更容易管理 O(n * lg(n))时间复杂度

Here's some information regarding Java's Array.sort()

答案 1 :(得分:1)

您可以继续使用Set,只需确保它从一开始就进行排序,例如TreeSet(如果您有多个线程,则为ConcurrentSkipListSet)。您可以实现Comparable以便比较时间戳,或者提供执行相同操作的Comparator。

这将保证您不会有重复项(就像您现在一样),并且还可以简化您的代码。插入TreeSet也会花费O(n log n)时间。

从这里开始,您可以继续使用Sam建议的方法:迭代器将按升序元素顺序遍历它,您需要将每个元素仅与前一个元素和下一个元素进行比较。

顺便说一句,你不需要将所有内容复制到另一个Set,只需确保使用迭代器的remove方法,而不是删除TreeSet:Iterating through a Collection, avoiding ConcurrentModificationException when removing in loop

答案 2 :(得分:0)

如果您有地图,请说:

Map<Long, List<MyClass>> map;

其中键是时间戳,那么你可以这样做:

// Value of wanted elements
List<MyClass> ret = new ArrayList<MyClass>();

// Go over all timestamps: if a timestamp is wanted, add all
// corresponding elements
for (Map.Entry<Long, List<MyClass>> entry: map.entrySet())
    if (wanted(entry.getKey()))
        ret.addAll(entry.getValue());

// Return
return ret;

答案 3 :(得分:0)

我没有测试性能,但我可能实现的一种方法是创建一个Set并覆盖有问题的对象类型的equals()方法。

public boolean equals( Object o )
{
  return( Math.abs( this.getTimestampSeconds() - o.getTimestampSeconds() ) < 15 );
}

通过这样做,当你将每一行添加到集合中时,对于任何给定的15秒时间片,你只会得到一个条目。

*编辑**

我不会对常规域对象执行此覆盖。我可能只会在某种类型的外观对象中执行此操作 - 仅为此目的而创建。

另外,正如其他人所说的那样。这假设您的输入列表按升序时间戳排序。