高性能设置类似于java的int数组的数据结构

时间:2013-10-11 16:03:38

标签: java performance scala

我正在寻找一个高性能的数据结构,其行为类似于一个集合,其中元素将始终是一个int数组。数据结构只需要实现这个接口:

trait SetX {
  def size:Int
  def add(element:Array[Int])
  def toArray:Array[Array[Int]]
}

该集合不应包含重复项,这可以使用Arrays.equals(int [] a,int [] a2)来实现 - 即数组的值不能相同。

在创建它之前,我大致了解将会有多少元素,但需要调整大小的行为,以防万一有多于最初的想法。元素将始终具有相同的长度,我知道创建时的内容。

当然我可以使用Java HashSet(当然包装数组),但这是在紧密循环中使用而且速度太慢。我看过Trove并且运行良好(通过使用数组但提供了TObjectHashingStrategy)但我希望由于我的要求如此具体,所以可能有更快/更有效的方法来实现这一点。

有没有人遇到这个或者知道如何才能做到这一点?

上面的特性是Scala,但我对Java库或代码非常满意。


我应该说出我在做什么。我基本上是在一个紧凑的循环中生成大量的int数组,在它的最后我只想看到独特的。我永远不必从集合或其他任何东西中删除元素。只需在集合中添加大量的int数组,最后就可以得到唯一的数组。

4 个答案:

答案 0 :(得分:1)

看看prefix trees。您可以在阵列生成期间立即遵循树结构。如果生成的数组已存在于集合中,那么在生成结束时您将得到答案。前缀树比普通的哈希集消耗更少的内存。

如果你正在生成阵列并且其等效性的可能性很小,我怀疑你只是从非常有限的范围内获取数字。它也会简化前缀树的实现。

我确信正确的实现比使用任何set实现来保持实体数组更快。

此解决方案的缺点是您需要自己实现数据结构,因为它将深深地与代码逻辑集成。

答案 1 :(得分:0)

不知道有多少数据,或者你是否正在做更多的读取而不是写:

您应该尝试(即基准测试)数组数组或特殊包装数组的数组(即具有数组缓存哈希码和数组的复合对象)的天真情况。通常在小数据集上没有多少跳过数组(例如,Enum的HashMap实际上比循环更慢)。

如果你有大量的数据且愿意做出妥协,你可能会考虑bloom filter,但听起来你没有太多数据。

答案 2 :(得分:0)

如果你想要高性能,那就写下自己的:

将其命名为ArraySetInt。

通常将集合实现为树或哈希表。

如果你想要一个基于数组的集合,这会减慢添加,可能会删除,但会加速迭代,低内存使用。等

首先看一下ArrayList的实现方式。 删除对象并用原始int替换它。

然后将add()重命名为put()并通过插入将其更改为排序类型。使用System.arraycopy()进行插入。使用Arrays.binsearch()来查找插入位置以及元素是否已经存在于一个步骤中。

答案 3 :(得分:0)

我会选择一个经典的解决方案,通过提供更快equalshashCode的类来包装数组。 hashCode可以简单地缓存,equals可以使用它来快速拒绝不同的数组。

我会避免Arrays.hashCode因为它使用了一个愚蠢的乘数(31),这可能会导致不必要的碰撞。对于一个非常快的equals,你可以使用密码学,并说两个数组是等于的,当且仅当它们的SHA-1相等时(你是第一个发现碰撞的数据:D)。 / p>

ArrayWrapper相当简单,应该比使用TObjectHashingStrategy更快,因为它永远不必查看数据本身(更少的缓存未命中),并且它具有最快和最好的hashCodeequals

你也可以寻找一些CompactHashSet实现,因为它可以更快,因为更好的内存局部性。