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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章