public class TEST { public static void main(String[] args) { List<Ad> list = new ArrayList<Ad>(); list.add(new Ad(1,5)); list.add(new Ad(2,10)); list.add(new Ad(3,20)); list.add(new Ad(4,30)); list.add(new Ad(5,35)); ComTest com = new ComTest(); Collections.sort(list,com); //对list中广告的权重要先排序,否则无法将随机数顺序安置到对应的区间 int id1=0; int id2=0; int id3=0; int id4=0; int id5=0; for (int i = 0; i < 100; i++) { int id = getAd(list); if(id==1) id1++; if(id==2) id2++; if(id==3) id3++; if(id==4) id4++; if(id==5) id5++; } System.out.println("12345:"+id1+"|"+id2+"|"+id3+"|"+id4+"|"+id5); } public static int getAd(List<Ad> list){ //根据权重返回对应id的方法 int sumWeight = 0; //得到总权重 for(Ad ad :list){ sumWeight+=ad.getWeight(); } Random rand = new Random(); int x = rand.nextInt(sumWeight) + 1; //生成随机数 int start = 0; int end = 0; for(int i=1;i<list.size();i++){ //计算各个权重对应的起止数值段 if(i==1){ start = list.get(i-1).getWeight(); end = list.get(i-1).getWeight()+list.get(i).getWeight(); }else{ start = end; end = start+list.get(i).getWeight(); } //根据随机数落入的范围返回对应几率的广告id if(x>start && x<=end){ return list.get(i).getId(); }else if(x<=start){ return list.get(i-1).getId(); }else{ continue; } } return 0; } }
class Ad{
public Ad(int id,int weight){ this.id = id; this.weight = weight; } int id; int weight;
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public int getWeight() { return weight; }
public void setWeight(int weight) { this.weight = weight; }
}
为了根据权重排序list而实现的comparator:import java.util.Comparator;public class ComTest implements Comparator<Ad> { public int compare(Ad o1, Ad o2) { if (o1.getWeight() < o2.getWeight()) { return -1; } else if (o1.getId() > o2.getId()) { return 1; } else { return 0; } } }
比如有个广告list,广告属性有id,weight,写个通用方法来根据权重显示广告id
//本以为很容易,看来想错了,看代码:
public class TEST { public static void main(String[] args) {
List<Ad> list = new ArrayList<Ad>();
list.add(new Ad(1,5));
list.add(new Ad(2,10));
list.add(new Ad(3,20));
list.add(new Ad(4,30));
list.add(new Ad(5,35));
ComTest com = new ComTest();
Collections.sort(list,com); //对list中广告的权重要先排序,否则无法将随机数顺序安置到对应的区间 int id1=0;
int id2=0;
int id3=0;
int id4=0;
int id5=0;
for (int i = 0; i < 100; i++) {
int id = getAd(list);
if(id==1) id1++;
if(id==2) id2++;
if(id==3) id3++;
if(id==4) id4++;
if(id==5) id5++;
}
System.out.println("12345:"+id1+"|"+id2+"|"+id3+"|"+id4+"|"+id5);
}
public static int getAd(List<Ad> list){ //根据权重返回对应id的方法
int sumWeight = 0; //得到总权重
for(Ad ad :list){
sumWeight+=ad.getWeight();
}
Random rand = new Random();
int x = rand.nextInt(sumWeight) + 1; //生成随机数
int start = 0; int end = 0;
for(int i=1;i<list.size();i++){
//计算各个权重对应的起止数值段
if(i==1){
start = list.get(i-1).getWeight();
end = list.get(i-1).getWeight()+list.get(i).getWeight();
}else{
start = end;
end = start+list.get(i).getWeight();
}
//根据随机数落入的范围返回对应几率的广告id
if(x>start && x<=end){
return list.get(i).getId();
}else if(x<=start){
return list.get(i-1).getId();
}else{
continue;
}
}
return 0;
}
}
class Ad{
public Ad(int id,int weight){
this.id = id;
this.weight = weight;
}
int id;
int weight;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
if (o1.getWeight() < o2.getWeight()) {
return -1;
} else if (o1.getId() > o2.getId()) {
return 1;
} else {
return 0;
}
}
}
Collections.sort(list,com); //对list中广告的权重要先排序,否则无法将随机数顺序安置到对应的区间
但是这个可有可无啊,我注释了,照样运行通过。
比如有3个广告权重是1、5、10,那么为了保证按正确的比率显示广告(显示几率为:1/16 , 5/16, 10/16),产生的随机数在 1、2-6之间、7-16之间,分别显示id1/2/3的广告。如果不先对权重排序,那么对应start/end那段代码就无法正确的计算出上面这3个区间(比如权重未排序是10、5、1,那么区间就计算成了1-10,10-15,15-16)。==我想想,啊对,可以不用排序,产生的范围虽然不是顺序的,但区间大小是正确的,可以取消排序类!你再试试