Java实现根据权重优先返回(速度较快)

不念不忘少年蓝@ 2022-09-25 04:14 304阅读 0赞

下面的实现比我最初写的快了四倍多哟。
实现思路
我们知道,在10以内的整数里,0~3出现的概率是0.3,3~6出现的概率是0.3,6~7出现的概率是0.1,7~9出现的概率是0.2,9~10出现的概率是0.1 ;上面对应的权重可对应为3 、3 、1、2 、1 。

所以,当我们需要实现不知道权重到底是多少时,我们只需要将所有权重加起来,假设为100,然后让随机数只出现0到100,接着给每个权重设定一个区间段,权重有多大,该区间段就有多宽,其中总区间就是总权重。

在组装我们的数据上也需要一定的技巧,我们用TreeMap来组装,key是区间段后面一个值,如下面0~4区间段对应的是4,然后将后面的值(如”4444“)放进value里。

生成在总权重范围内的随机数,假设是2;然后我们根据TreeMap的ceilingKey(2) 方法获得大于等于2的最键,这里得到是4。这样就能去TreeMap里取到我们需要的值了

  1. 下面数据对应区间段:0~4 44444~11777711~14333314~184242
  2. public class 权重 {
  3. //测试
  4. public static void main(String[] args) {
  5. String[] str1 = {
  6. "4","4444"}; //权重为4
  7. String[] str2 = {
  8. "7","7777"}; //权重为7
  9. String[] str3 = {
  10. "3","3333"}; //权重为3
  11. String[] str4 = {
  12. "4","4242"}; //权重为4
  13. List<String[]> list = new ArrayList<String[]>();
  14. list.add(str1);
  15. list.add(str2);
  16. list.add(str3);
  17. list.add(str4);
  18. Long s = System.currentTimeMillis();
  19. String str = null;
  20. for(int i=0;i<10000000;i++){
  21. str = new 权重().getMax(list);
  22. }
  23. Long e = System.currentTimeMillis();
  24. System.out.println("耗时:"+(e-s));
  25. System.out.println(str);
  26. //String result = new 权重().getMax(list);
  27. }
  28. /** * 获得给定List集合里权重大的结果 * @param list * @return * @author Peter */
  29. public String getMax(List<String[]> list){
  30. int len = list.size();
  31. int total = 0;//总权重
  32. //以权重区间段的后面的值作为key存当前信息
  33. TreeMap<Integer,String> map = new TreeMap<Integer, String>();
  34. for(int i=0; i<len; i++){
  35. String[] array = list.get(i);
  36. total += Integer.parseInt(array[0]);
  37. map.put(total, array[1]);
  38. }
  39. int random = (int)(Math.random()*total);
  40. Integer key = map.ceilingKey(random);
  41. return map.get(key);
  42. }
  43. }

思考
下面的实现只是说在有10000万人的用户去取的速度快;但如果list里的数据有1千万条,而我们只取一次时的速度就没什么多大的提高,原因是于组成Map的时候耗时太多,如果我们将耗时的过程存为静态,即只在第一次访问时组装。当然,这里机List是不变的,如果List是变化的则只能用上面的方式

  1. public class 权重 {
  2. private static int total=0;
  3. private static TreeMap<Integer,String> map = null;
  4. //组装数据
  5. static{
  6. System.out.println("静态块只在第一次调用时执行");
  7. List<String[]> list = new ArrayList<String[]>();
  8. String[] str1 = {
  9. "1","5511155"};
  10. String[] str2 = {
  11. "2","5555555"};
  12. String[] str3 = {
  13. "3","55588885"};
  14. String[] str4 = {
  15. "2","500000000555"};
  16. list.add(str1);
  17. list.add(str2);
  18. list.add(str3);
  19. list.add(str4);
  20. for(int i=0;i<1000000;i++){
  21. //1千万条数据
  22. list.add(str4);
  23. }
  24. int len = list.size();
  25. int total = 0;//总权重
  26. //以权重区间段的后面的值作为key存当前信息
  27. /*TreeMap<Integer,String>*/
  28. map = new TreeMap<Integer, String>();
  29. for(int i=0; i<len; i++){
  30. String[] array = list.get(i);
  31. total += Integer.parseInt(array[0]);
  32. map.put(total, array[1]);
  33. }
  34. }
  35. /** * 获得给定List集合里权重大的结果 * @param list * @return * @author Peter */
  36. public String getMax(){
  37. int random = (int)(Math.random()*total);
  38. Integer key = map.ceilingKey(random);
  39. return map.get(key);
  40. }
  41. }

发表评论

表情:
评论列表 (有 0 条评论,304人围观)

还没有评论,来说两句吧...

相关阅读