使用Java从大整数数组中删除重复项

时间:2010-09-08 12:08:19

标签: java arrays loops integer

您是否知道有时使用Java从非常大的整数数组中删除重复值的有效方法?数组的大小取决于登录用户,但总是超过1500000个未排序的值和一些重复项。每个整数都包含一个介于100000和9999999之间的数字。

我尝试将其转换为List,但我服务器上的堆不允许这么多数据(我的ISP限制了它)。 for循环中的常规for循环需要5分钟才能计算出来。

没有重复项的数组的大小是我将存储在数据库中的数据。

帮助将不胜感激!

9 个答案:

答案 0 :(得分:37)

您可以使用一下套装吗?我不知道Java的BitSet有多高效。但是9999999可能的值只需要9999999/8 = 1250000字节=仅超过1Mb。在遍历值数组时,将相应位设置为true。然后,只要找到一个设置为true的位,就可以遍历位集并输出相应的值。

1Mb将适合CPU缓存,因此根据位集实现,这可能非常有效。

这也有排序数据的副作用。

而且......这是一个O(n)算法,因为它需要对输入数据进行单次传递,设置操作为O(1)(对于像这样的基于数组的集合),输出传递是还有O(m)其中m是唯一值的数量,根据定义,必须是< = n。

答案 1 :(得分:3)

在开始向列表中添加项目之前,我会创建一个hashset,用于存储列表中包含的所有值。然后检查以便hashset不包含您要添加的值。

答案 2 :(得分:3)

Set<Integer> set = new HashSet<Integer>();
Collections.addAll(set, array);

您只需要一个Integer[]而不是int[]的数组。

答案 3 :(得分:2)

您可以先尝试排序数组:

int arr[] = yourarray;
Arrays.sort(arr);
// then iterate arr and remove duplicates

答案 4 :(得分:1)

int[] a;
Arrays.sort(a);
int j = 0;
for (int i = 1; i < a.length; ++i) {
  if (a[i] != a[j]) {
    ++j;
    a[j] = a[i];
  }
}
// now store the elements from 0 to j (inclusive - i think)

答案 5 :(得分:1)

真正绝望的人可以将数组写入磁盘并分叉sort | uniq | wc -l <infile.txt并捕获输出。如果内存仍然太紧或整数的域空间变大,则需要这样做。我不喜欢这个(他甚至运行unix!)但我的观点是有许多方法来完成任务。

另一个观察结果是最小值为100,000。因此,我们可以从最大值9,999,999中减去100,000,从而减少了域空间,从而节省了一些内存。也许100k / 8位是花生的方案,但它基本上是免费的。

答案 6 :(得分:0)

也许你可以对数据进行一些传递?例如,如果您对数据进行了10次传递,并将上述一组建议应用于较小的数据子集(例如,当值mod传递#== 0时)。因此:

for (int i = 0 to 9) {
  set = new Set()
  for (each entry in the data set) {
    if (entry % i == 0) {
      set.add(entry)
    }
  }
  output set
}

通过这种方式,您可以换取内存的时间(增加内存数量,减少内存/更多时间,反之亦然)。

答案 7 :(得分:0)

也许使用原语而不是对象的哈希集会完成这项工作?有免费的实现(之前没有使用它们,但也许它可以工作):

http://trove4j.sourceforge.net/

http://trove4j.sourceforge.net/javadocs/gnu/trove/TIntHashSet.html

然后看起来像:

int[] newArray = new TIntHashSet(yourArray).toArray();

答案 8 :(得分:0)

如果您确定,整数具有合理的小值(例如总是大于零且小于1000或10000),您可以尝试这样的技巧:

    final int MAX = 100; 
    int[] arrayWithRepeats = {99, 0, 10, 99, 0, 11, 99};

    //we are counting here integers with the same value
    int [] arrayOfValues = new int[MAX+1];
    int countOfUniqueIntegers = 0;
    for(int i : arrayWithRepeats) {
        if(arrayOfValues[i] == 0) {
            countOfUniqueIntegers++;
        }
        arrayOfValues[i]++;
    }

    // you can use arrayOfValues (smaller) or convert it
    // to table of unique values (more usable)

    int[] arrayOfUniqueValues = new int[countOfUniqueIntegers];
    int index = 0;
    for(int i = 0; i<arrayOfValues.length; i++) {
        if(arrayOfValues[i] != 0) {
            arrayOfUniqueValues[index] = i;
            index++;
        }
    }

    //and now arrayOfUniqueValues is even sorted
    System.out.println( Arrays.toString(arrayOfUniqueValues) );

输出:[0,10,11,99]