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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_38789941/article/details/93715894

 应用场景:

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

 实现原理:

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


落实到代码:

@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;
	}  
}

猜你喜欢

转载自blog.csdn.net/qq_38789941/article/details/93715894