java中根据权重随机获取数据

 应用场景:

有时我们需要从一些列数据中根据权重随机选取指定条数记录出来,这里需要权重、随机,我们根据权重越大的,出现概率越大。例如广告系统。

 实现原理:

需求确认后在网上找了很多的资料,可惜没有比较合适的方案,下面和大家分享一种,有不合理之处还请大家指正。废话少说,其实算法很简单,如下:


落实到代码:

@Service
public class AdvertiseService extends BaseService{
	private static final Logger log = LoggerFactory.getLogger(AdvertiseService.class);
	
	static List<WeightCategory>  categorys = new ArrayList<WeightCategory>();
	private static Random random = new Random(); 
	
	@Autowired
	private RedisService redisService;
	@Value("${redis.cache.time}")
	private int redisCacheTime;
	
	
	/**
	 * 通过权重获取Id
	 */
	private String weightRandomId() {
		// 获取权重集合
		getAdvertiseWeightList();
		
		Integer weightSum = 0;
		String advertiseId = null;
		for (WeightCategory wc : categorys) {
			weightSum += wc.getWeight();
		}

		if (weightSum <= 0) {
			log.info("Error: weightSum=" + weightSum.toString());
			return null;
		}
		Integer n = random.nextInt(weightSum); // n in [0, weightSum)
		Integer m = 0;
		for (WeightCategory wc : categorys) {
			if (m <= n && n < m + wc.getWeight()) {
				advertiseId = wc.getAdvertiseId();
				log.info("This Random advertiseId is " + advertiseId);
				break;
			}
			m += wc.getWeight();
		}
		return advertiseId;
	}

	
	/**
	 * 获取广告权重list
	 */
	private void getAdvertiseWeightList() {
		
		// 从缓存中获取
		String key = getKey("getAdvertiseList");
		if (redisService.exists(key)) {
			String value = redisService.get(key);
			if (StringUtils.isNotBlank(value)) {
				categorys =  JSON.parseObject(value, advertiseListType);
			}
		} else {
			// 从数据库中获取
			List<Advertise> list = shopAdvertiseService.list();
			if (list != null && list.size() > 0) {
				// 清空数据
				categorys.clear();
				// 获取权重
				for (Advertise advertise : list) {
					// 添加数据
					categorys.add(new WeightCategory(advertise.getId(), advertise.getWeight()));
				}
				// 存入redis缓存
				redisService.setex(key, JSON.toJSONString(categorys), redisCacheTime);
			}
		}
	}
	
}

class WeightCategory {  
	private String advertiseId;  
	private Integer weight;
	
	public String getAdvertiseId() {
		return advertiseId;
	}
	public void setAdvertiseId(String advertiseId) {
		this.advertiseId = advertiseId;
	}
	public Integer getWeight() {
		return weight;
	}
	public void setWeight(Integer weight) {
		this.weight = weight;
	}
	public WeightCategory() {
		super();
	}
	public WeightCategory(String advertiseId, Integer weight) {
		super();
		this.advertiseId = advertiseId;
		this.weight = weight;
	}  
}

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值