我正在尝试创建一个包含10亿个随机排序的非重复数字的文本文件。我创建了以下代码,但在完成(堆满)之前我的内存耗尽。我正在寻找关于如何创建此txt文件的建议或代码更正。
private int maxSize = 1000000000;
private int minimum = 1;
try {
ArrayList<Integer> arrayList = new ArrayList<Integer>();
for(int i = minimum - 1; i < maxSize; i++){
arrayList.add( i);
}
numlist.close();
// shuffle 10 times for true mix up
for(int j = 0; j < 10; j++){
Collections.shuffle(arrayList);
}
BufferedWriter numlist = new BufferedWriter(new FileWriter("randomNumbersNoRepeats.txt"));
for(int i = minimum - 1; i < maxSize; i++){
System.out.println(i);
numlist.write(i + ",");
}
numlist.close();
} catch (Exception e) {
System.out.println("Error in creating writer new bufferWriter"
+ " for randomNumbersNoRepeats.txt");
}
答案 0 :(得分:3)
宣告:
private static final int maxSize = 1_000_000_000;
static int[] array = new int[maxSize];
使用非重复数字填充数组,例如array[i] = i + 1;
。
编写一个使用Fisher–Yates shuffle algorithm的混洗方法。这不需要多行代码,所以我认为我不需要为你做这些。
使用类似-Xmx10G
VM参数的程序运行程序。这将确保为数组分配足够的堆空间。
感谢Andy Turner的灵感。编辑:安迪继续鼓舞:要一次性初始化和随机播放数组,您可以使用同一维基百科文章中描述的inside-out algorithm。在Java中:
Random r = new Random();
for (int i = 0; i < maxSize; i++) {
int j = r.nextInt(i + 1);
if (j != i) {
array[i] = array[j];
}
array[j] = i + 1;
}
答案 1 :(得分:0)
Mabye你可以扩展Stack类来创建一个随机位置弹出的堆栈。
以下是我放在一起的例子:
public class ExtendedStack<E> extends Stack
{
public static void main(String[] args)
{
ExtendedStack stack = new ExtendedStack<Integer>();
for (int i = 0; i < 10; i++)
{
stack.push(i);
}
Integer random = (Integer) stack.popRandom();
System.out.println(random);
}
public synchronized E popRandom()
{
E obj;
int len = size();
int randomLocation = randomLocation(len);
obj = (E) elementAt(randomLocation);
removeElementAt(randomLocation);
return obj;
}
private int randomLocation(int len)
{
return new Random().nextInt(len + 1);
}
}
有关Java中堆栈的更多信息:
https://docs.oracle.com/javase/7/docs/api/java/util/Stack.html
答案 2 :(得分:0)
有关ArrayList的一件事是,当调用add()函数时,每次空间用完时,它会自动将其分配的空间增加50%。如果允许它以这种方式增长,最终将会有大量未使用的分配空间。在这个例子中,它将耗尽839k元素的空间,增加50%到12.6亿个元素。额外的2.66亿条款的空间被浪费了!因此,您可以通过使用
声明创建时的阵列容量来减少20%的内存ArrayList<Integer> arrayList = new ArrayList<Integer>(1000000000);
话虽如此,你还有十亿美元的赌注会使用3GB的内存。那是一大堆。查看this thread有关如何增加堆大小的信息。然后尝试仅创建具有声明容量的arraylist,以确保您现在有足够的内存可用于其完整大小。
最后,您可以在编写它们之后从ArrayList中删除条目以释放空间
for(int i = minimum - 1; i < maxSize; i++){
System.out.println(arraylist.get(0));
numlist.write(arraylist.get(0) + ",");
arraylist.remove(0);
}
(顺便说一下你的原始代码写入文件迭代变量而不是存储在ArrayList中的值。)我不认为缓冲的编写器应该耗尽太多的内存但是如果你有额外的操作这个步骤可能会很有用在这段代码之后。