您是否知道有时使用Java从非常大的整数数组中删除重复值的有效方法?数组的大小取决于登录用户,但总是超过1500000个未排序的值和一些重复项。每个整数都包含一个介于100000和9999999之间的数字。
我尝试将其转换为List,但我服务器上的堆不允许这么多数据(我的ISP限制了它)。 for循环中的常规for循环需要5分钟才能计算出来。
没有重复项的数组的大小是我将存储在数据库中的数据。
帮助将不胜感激!
答案 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]