Если посмотреть на ответ Итая, похоже, что он читает файл тысячу раз после выборки одной строки кода, тогда как истинная выборка из резервуара должна проходить через «ленту» только один раз. Я разработал некоторый код для однократного прохождения кода с реальной выборкой из пласта, основываясь на this и различных описаниях в Интернете.
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
public class reservoirSampling {
public static void main(String[] args) throws FileNotFoundException, IOException{
Sampler mySampler = new Sampler();
List<String> myList = mySampler.sampler(10);
for(int index = 0;index<myList.size();index++){
System.out.println(myList.get(index));
}
}
}
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
public class Sampler {
public Sampler(){}
public List<String> sampler (int reservoirSize) throws FileNotFoundException, IOException
{
String currentLine=null;
//reservoirList is where our selected lines stored
List <String> reservoirList= new ArrayList<String>(reservoirSize);
// we will use this counter to count the current line number while iterating
int count=0;
Random ra = new Random();
int randomNumber = 0;
Scanner sc = new Scanner(new File("Open_source.html")).useDelimiter("\n");
while (sc.hasNext())
{
currentLine = sc.next();
count ++;
if (count<=reservoirSize)
{
reservoirList.add(currentLine);
}
else if ((randomNumber = (int) ra.nextInt(count))<reservoirSize)
{
reservoirList.set(randomNumber, currentLine);
}
}
return reservoirList;
}
}
Основная предпосылка заключается в том, что вы заполняете резервуар, а затем возвращаетесь к нему и заполняете случайные линии с вероятностью 1 / ReservoirSize. Я надеюсь, что это обеспечивает более эффективный код. Пожалуйста, дайте мне знать, если это не сработает для вас, потому что я буквально выбил его за полчаса.