public class Test {
@Data
private static class ABTestEntity {
private long id;
private int percent;
public ABTestEntity(long id, int percent) {
this.id = id;
this.percent = percent;
}
}
public static void main(String[] args) throws Exception {
long uid = 4L;
long strategyId = 123456L;
List<ABTestEntity> configs = new ArrayList<>();
configs.add(new ABTestEntity(1, 10));
configs.add(new ABTestEntity(2, 20));
configs.add(new ABTestEntity(3, 30));
configs.add(new ABTestEntity(4, 40));
System.out.println(executeDiversion(uid, configs, strategyId));
}
/**
* 執(zhí)行分流請求
*
* @param strategyId 策略ID,由于用戶分組結(jié)果對于某個策略是一定的,所以我們的業(yè)務(wù)上使用策略ID作為離散因子
*/
private static Long executeDiversion(long uid, List<ABTestEntity> abTestEntityList, Long strategyId) throws Exception {
if (abTestEntityList != null) {
ArrayList<Long> abTestIdArr = new ArrayList<Long>();
ArrayList<Integer> percentArr = new ArrayList<Integer>();
int value = 0;
for (ABTestEntity abTestEntity : abTestEntityList) {
long abtestId = abTestEntity.getId();
value += abTestEntity.getPercent();
abTestIdArr.add(abtestId);
percentArr.add(value);
}
return getDivResultMap(Long.toString(uid), Long.toString(strategyId), abTestIdArr, percentArr, value);
}
return -1L;
}
/**
* 返回層分流結(jié)果
*
* @param uid eg:4
* @param shuffle eg:123456 離散因子
* @param bucketIdArr eg:[1,2,3,4] 四個分組
* @param percentArr eg:[10,30,60,100] 當(dāng)前分組和前幾個分組累加的比例
* @param value eg: 100 所有分組共占得比例
* @return
*/
private static Long getDivResultMap(String uid, String shuffle, ArrayList<Long> bucketIdArr, ArrayList<Integer> percentArr, int value) throws Exception {
MessageDigest md5 = MessageDigest.getInstance("MD5");/* 用來生成MD5值 */
long hashValue = splitBucket(md5, uid, shuffle);
if (value > 0) {
int bucket = (int) (hashValue % value) + 1;// 將比例分成value份,看每次請求落在某份上
// eg: bucket = 83
for (int i = 0; i < percentArr.size(); i++) {
if (bucket <= percentArr.get(i)) {
return bucketIdArr.get(i);
}
}
}
return -1L;
}
/**
* 對用戶標(biāo)識進(jìn)行hash
*
* @param md5 加密算法
* @param val 用戶請求標(biāo)識(uv:uid pv:uid+timestamp)
* @param shuffle :離散因子
* @return
*/
public static long splitBucket(MessageDigest md5, String val, String shuffle) {
String key = val + ((shuffle == null) ? "" : shuffle);
byte[] ret = md5.digest(key.getBytes());
String s = byteArrayToHex(ret);
long hash = Long.parseLong(s.substring(s.length() - 16, s.length() - 1), 16);
if (hash < 0) {
hash = hash * (-1);
}
return hash;
}
public static String byteArrayToHex(byte[] byteArray) {
char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
char[] resultCharArray = new char[byteArray.length * 2];
int index = 0;
for (byte b : byteArray) {
resultCharArray[index++] = hexDigits[b >>> 4 & 0xf];
resultCharArray[index++] = hexDigits[b & 0xf];
}
return new String(resultCharArray);
}
}
Java-ABTest對用戶按策略分組
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
相關(guān)閱讀更多精彩內(nèi)容
- !DOCTYPE html>Bizpower商城系統(tǒng)演示站 - Powered by Bizpowerhttp:/...
- 今天是釘釘應(yīng)用云開發(fā)實(shí)戰(zhàn)營的第3課,聽課的時候,感覺老師講得內(nèi)容挺好,只是知識點(diǎn)有點(diǎn)散,一度擔(dān)心,像我這樣的小白能...
- [https://github.com/GourdErwa/review-notes/blob/master/la...
- 1. HashMap原理 jdk8后采用數(shù)組+鏈表+紅黑樹的數(shù)據(jù)結(jié)構(gòu),利用元素的key的hash值對數(shù)組長度取模得...
- 1. jps : 虛擬機(jī)進(jìn)程狀況工具[#1-jps-%E8%99%9A%E6%8B%9F%E6%9C%BA%E8%...