Java 随着时间的推移,以概率方式选择一定数量的项目
我有一个在服务器上运行的企业应用程序,它接受文件。用户每天提交数以万计的文件。客户希望每天自动选择其中50个文件进行审核 这些要求是:Java 随着时间的推移,以概率方式选择一定数量的项目,java,math,probability,Java,Math,Probability,我有一个在服务器上运行的企业应用程序,它接受文件。用户每天提交数以万计的文件。客户希望每天自动选择其中50个文件进行审核 这些要求是: 文件进入时必须选择(我们不能等待所有文件进入,然后在一天结束时选择50个) 选择的文件必须符合其他一些标准,他们还没有告诉我,但我确信仍有数千个文件符合这些标准 系统不能是“可玩游戏的”。也就是说,他们不希望提交文件的用户意识到,如果他们等到下午什么的,他们的文件永远不会被审核。这意味着我们不能只选择前50个文件,选择的文件必须在一天中随机分布 我们必须有50个
package com.playground;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Random;
public class ProbabilisticSelection {
private static int TOTAL_FILES = 1000;
private static int AUDIT_QUANTITY = 10;
private static int TIME_IN_SECONDS_FOR_ALL_FILES = 10;
private Random random = new Random();
private Deque<String> stack = new ArrayDeque<String>();
private boolean finished;
public static void main(String[] args) throws InterruptedException {
new ProbabilisticSelection().test();
}
private void test() throws InterruptedException {
Instant begin = Instant.now();
Runnable pushTask = () -> {
while (!finished) {
int next = random.nextInt(TOTAL_FILES);
String item = "File: " + next;
stack.push(item);
if (Duration.between(begin, Instant.now()).getSeconds() >= TIME_IN_SECONDS_FOR_ALL_FILES) {
finished = true;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable pullTask = () -> {
int itemNumber = 1;
while (itemNumber <= AUDIT_QUANTITY && !finished) {
String poll = stack.poll();
if (requirementsFunction(poll) &&
probabilityFunction(itemNumber, Duration.between(begin, Instant.now()))) {
System.out.println(itemNumber++ + ": "+ poll);
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
finished = true;
Duration delta = Duration.between(begin, Instant.now());
System.out.println();
System.out.println("Retrieved files: " + (itemNumber - 1) + ", should be, " + AUDIT_QUANTITY);
System.out.println("Time taken: " + delta.getSeconds() + ", should be, " + TIME_IN_SECONDS_FOR_ALL_FILES);
};
new Thread(pullTask).start();
new Thread(pushTask).start();
}
private boolean requirementsFunction(String item) {
return item != null && item.endsWith("0");
}
private boolean probabilityFunction(int itemNumber, Duration delta) {
double limit = ((double)(AUDIT_QUANTITY-itemNumber)/(double)AUDIT_QUANTITY + 1); // probability goes down as number of items goes up
double tension = (double)TIME_IN_SECONDS_FOR_ALL_FILES/((double)delta.getSeconds() + 1); // probablity goes up as time nears the end
if (tension == 1) {
return true;
}
double prob = limit * tension * 100;
int rand = random.nextInt(1000);
return prob > rand;
}
}
package.com;
导入java.time.Duration;
导入java.time.Instant;
导入java.util.ArrayDeque;
导入java.util.Deque;
导入java.util.Random;
公共类概率统计选举{
私有静态int-TOTAL_文件=1000;
私有静态int审计_数量=10;
所有文件的私有静态整数时间(以秒为单位)=10;
私有随机=新随机();
private Deque stack=new ArrayDeque();
私有布尔完成;
公共静态void main(字符串[]args)引发InterruptedException{
新概率选择().test();
}
private void test()引发InterruptedException{
即时开始=即时。现在();
可运行的pushTask=()->{
当(!完成){
int next=random.nextInt(文件总数);
String item=“文件:”+下一步;
堆栈。推送(项目);
if(Duration.between(begin,Instant.now()).getSeconds()>=所有文件的时间(单位:秒){
完成=正确;
}
试一试{
睡眠(10);
}捕捉(中断异常e){
e、 printStackTrace();
}
}
};
Runnable pullTask=()->{
int itemNumber=1;
while(项目编号);
}
}
算法被调用,它保证了从一些大型和未知的N
项目中公平地采样k
项目。以下是Java我知道沿着这条路线走听起来是一件非常痛苦的事情,但是是否可以使用一个近似函数来根据应用程序在一段时间内记录的实际数据进行提交分布周期?然后将此分布输入选择标准。不幸的是,对我来说,一旦文件被“选择”,我就无法“取消选择”。似乎水库采样填充了“水库”然后以一定的概率替换一个项目,使储液罐总是满的。我不能这样做。@PhilBarr,那么你想要的是不可能的。使用储液罐采样,单个项目的概率是1/N,无论N是什么,即使你事先不知道。如果你不能移除项目,那么根据定义,第一个被选择的项目将具有更高的概率,无论您部署什么算法-它们都是从前K个项目中选择的,K