Java 快速遍历集合并删除满足特定条件的项的方法

Java 快速遍历集合并删除满足特定条件的项的方法,java,performance,data-structures,collections,Java,Performance,Data Structures,Collections,所以我有一个程序,其中包含一组记录。这套装置可能有几个项目,或者可能有几十万个项目。每个记录的一位数据是一个时间戳。我需要消除一组中的所有项目,但一个项目彼此之间的间隔不超过15秒。最有效的方法是什么 目前,我创建了该集合的副本。然后我遍历集合,将第一个项目与其他每个项目进行比较,然后重复。如果在15秒内找到匹配项,我会将其从复制集中删除。然后将重复集写入文件 显然,这是可行的,但我最终意识到,这是荒谬的效率低下。对于大型集合来说,假设没有其他问题发生,这似乎需要花费很长时间。有人能为我提供一种

所以我有一个程序,其中包含一组记录。这套装置可能有几个项目,或者可能有几十万个项目。每个记录的一位数据是一个时间戳。我需要消除一组中的所有项目,但一个项目彼此之间的间隔不超过15秒。最有效的方法是什么

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

显然,这是可行的,但我最终意识到,这是荒谬的效率低下。对于大型集合来说,假设没有其他问题发生,这似乎需要花费很长时间。有人能为我提供一种更智能、更快、更高效(或者只是一种合适的)方法来用Java实现这一点吗?我意识到,因为这些记录包含时间戳,所以对它们进行排序可能会有很大帮助。我想把这些都包含在程序中,所以我想我需要研究排序和比较器

我就是不能完全理解这个问题。我已经想出了一些其他的想法来改进我的代码,但我还是忍不住觉得我在这个问题上仍然是完全错误的。谢谢你的建议


哦,这是工作用的,不是学校用的,所以我们非常感谢您的帮助。

现在,您描述的算法在O(n2)时间内运行

现在,如果你需要一个更快的算法,你能做的就是

  • 对集合进行排序(如果java没有基类排序函数,我会感到惊讶)O(n*lg(n))
  • 在15秒内的所有“匹配”都将彼此紧挨着
  • 只需对每个元素迭代一次,只需检查相邻元素O(n)
如果您这样做,那么您的算法可能会变得更加易于管理O(n*lg(n))时间复杂度


现在,您描述的算法在O(n2)时间内运行

现在,如果你需要一个更快的算法,你能做的就是

  • 对集合进行排序(如果java没有基类排序函数,我会感到惊讶)O(n*lg(n))
  • 在15秒内的所有“匹配”都将彼此紧挨着
  • 只需对每个元素迭代一次,只需检查相邻元素O(n)
如果您这样做,那么您的算法可能会变得更加易于管理O(n*lg(n))时间复杂度


如果你有地图,说:

Map<Long, List<MyClass>> map;
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;
//所需元素的值
List ret=new ArrayList();
//检查所有时间戳:如果需要时间戳,则添加所有时间戳
//对应元素
对于(Map.Entry:Map.entrySet())
如果需要(entry.getKey())
ret.addAll(entry.getValue());
//返回
返回ret;

如果你有地图,说:

Map<Long, List<MyClass>> map;
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;
//所需元素的值
List ret=new ArrayList();
//检查所有时间戳:如果需要时间戳,则添加所有时间戳
//对应元素
对于(Map.Entry:Map.entrySet())
如果需要(entry.getKey())
ret.addAll(entry.getValue());
//返回
返回ret;

您可以继续使用集合,只需确保从一开始就对其进行排序,如(或者如果您有多个线程)。要么实现Comparable以便比较时间戳,要么提供一个比较器来执行相同的操作

这将保证您不能有重复的代码(就像您到目前为止所拥有的一样),并简化您的代码。插入到树集中也会花费你O(n logn)时间

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


顺便说一句,您不需要将所有内容复制到另一个集合,只需确保使用迭代器的remove方法,而不是删除TreeSet:

您可以继续使用集合,只需确保它从一开始就排序,如(或者如果您有多个线程)。要么实现Comparable以便比较时间戳,要么提供一个比较器来执行相同的操作

这将保证您不能有重复的代码(就像您到目前为止所拥有的一样),并简化您的代码。插入到树集中也会花费你O(n logn)时间

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


顺便说一句,您不需要将所有内容复制到另一个集合,只需确保使用迭代器的remove方法,而不是TreeSet的remove方法:

我还没有测试性能,但我可能实现这一点的一种方法是创建一个集合,并覆盖所讨论的对象类型的equals()方法

public boolean equals( Object o )
{
  return( Math.abs( this.getTimestampSeconds() - o.getTimestampSeconds() ) < 15 );
}
公共布尔等于(对象o)
{
返回(Math.abs(this.getTimestampSeconds()-o.getTimestampSeconds())<15);
}
通过这样做,当您将每一行添加到集合中时,对于任何给定的15秒时间片,您将只得到一个条目

*编辑**

我不会对常规域对象执行此重写。我可能只会在某种类型的facade对象中执行此操作,而facade对象是专门为此目的创建的


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

我还没有测试性能,但实现这一点的一种方法是创建一个集合并重写