Java權(quán)重隨機(jī)的實(shí)現(xiàn)方法
本文實(shí)例講述了Java權(quán)重隨機(jī)的實(shí)現(xiàn)方法。分享給大家供大家參考。具體分析如下:
權(quán)重隨機(jī)在項(xiàng)目中經(jīng)常用到,所以我把它抽象到一個(gè)工具類中。
一般實(shí)現(xiàn)隨機(jī)權(quán)重有兩種方式:
1. 使用一個(gè)數(shù)組存放權(quán)重對(duì)應(yīng)的實(shí)際目標(biāo),比如A的權(quán)重是2,B的權(quán)重是3,那么數(shù)組長(zhǎng)度為5, 數(shù)組前兩個(gè)存放A,后三個(gè)存放B。
然后隨機(jī)一個(gè)[0-數(shù)據(jù)長(zhǎng)度)的數(shù)字,直接取數(shù)組對(duì)應(yīng)下標(biāo)的值就可以了。
優(yōu)點(diǎn):數(shù)據(jù)結(jié)構(gòu)簡(jiǎn)單,算法高效,實(shí)現(xiàn)簡(jiǎn)單
缺點(diǎn):當(dāng)權(quán)重值比較大同時(shí)數(shù)據(jù)又比較多的時(shí)候,會(huì)浪費(fèi)內(nèi)存
2. 使用區(qū)間算法,從前到后依次疊加權(quán)重,然后隨機(jī)一個(gè)[1-權(quán)重和]的數(shù)字,再用隨機(jī)的權(quán)重依次減去每個(gè)元素的權(quán)重,當(dāng)?shù)谝粋€(gè)小于等于0的元素就是我們找元素
這里實(shí)現(xiàn)可以借用Arrays的binarySearch方法。
完整實(shí)例代碼點(diǎn)擊此處本站下載。
貼一下代碼:
WeightMeta.java:
* 建議使用RandomUtil類創(chuàng)建RandomMeta對(duì)象
* @author wxf on 14-5-5.
*/
public class WeightMeta<T> {
private final Random ran = new Random();
private final T[] nodes;
private final int[] weights;
private final int maxW;
public WeightMeta(T[] nodes, int[] weights) {
this.nodes = nodes;
this.weights = weights;
this.maxW = weights[weights.length - 1];
}
/**
* 該方法返回權(quán)重隨機(jī)對(duì)象
* @return
*/
public T random() {
int index = Arrays.binarySearch(weights, ran.nextInt(maxW) + 1);
if (index < 0) {
index = -1 - index;
}
return nodes[index];
}
public T random(int ranInt) {
if (ranInt > maxW) {
ranInt = maxW;
} else if(ranInt < 0){
ranInt = 1;
} else {
ranInt ++;
}
int index = Arrays.binarySearch(weights, ranInt);
if (index < 0) {
index = -1 - index;
}
return nodes[index];
}
@Override
public String toString() {
StringBuilder l1 = new StringBuilder();
StringBuilder l2 = new StringBuilder("[random]\t");
StringBuilder l3 = new StringBuilder("[node]\t\t");
l1.append(this.getClass().getName()).append(":").append(this.hashCode()).append(":\n").append("[index]\t\t");
for (int i = 0; i < weights.length; i++) {
l1.append(i).append("\t");
l2.append(weights[i]).append("\t");
l3.append(nodes[i]).append("\t");
}
l1.append("\n");
l2.append("\n");
l3.append("\n");
return l1.append(l2).append(l3).toString();
}
}
RandomUtil.java:
* 隨機(jī)工具類
*
* 使用權(quán)重的集合Map構(gòu)建隨機(jī)元數(shù)據(jù)對(duì)象
*
* 比如:
* 我們有3個(gè)url地址,他們的權(quán)重分別為1,2,3現(xiàn)在我們利用RandomUtil來(lái)根據(jù)權(quán)重隨機(jī)獲取url:
*
* <p><blockquote><pre>
*
* map.put(url1, 1);
* map.put(url2, 2);
* map.put(url3, 3);
* RandomMeta<String, Integer> md = RandomUtil.buildWeightMeta(map);
* String weightRandomUrl = md.random();
*
* </pre></blockquote><p>
*
* @author wxf on 14-5-5.
*/
public class RandomUtil {
public static <T> WeightMeta<T> buildWeightMeta(final Map<T, Integer> weightMap) {
final int size = weightMap.size();
Object[] nodes = new Object[size];
int[] weights = new int[size];
int index = 0;
int weightAdder = 0;
for (Map.Entry<T, Integer> each : weightMap.entrySet()) {
nodes[index] = each.getKey();
weights[index++] = (weightAdder = weightAdder + each.getValue());
}
return new WeightMeta<T>((T[]) nodes, weights);
}
}
希望本文所述對(duì)大家的Java程序設(shè)計(jì)有所幫助。
相關(guān)文章
使用@ControllerAdvice同時(shí)配置過(guò)濾多個(gè)包
這篇文章主要介紹了使用@ControllerAdvice同時(shí)配置過(guò)濾多個(gè)包的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
小白必看toString(),String.valueOf,(String)強(qiáng)轉(zhuǎn)
在Java中,往往需要把一個(gè)類型的變量轉(zhuǎn)換成String 類型,本文主要介紹了toString(),String.valueOf,(String)強(qiáng)轉(zhuǎn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06
關(guān)于java.math.BigDecimal比較大小問(wèn)題
這篇文章主要介紹了關(guān)于java.math.BigDecimal比較大小問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
java calendar 日期實(shí)現(xiàn)不斷加一天的代碼
這篇文章主要介紹了java calendar 日期實(shí)現(xiàn)不斷加一天的代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10
多線程Thread,Runnable,Callable實(shí)現(xiàn)方式
這篇文章主要為大家詳細(xì)介紹了Java多線程如何實(shí)現(xiàn)Thread,Runnable,Callable的方式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
Springcloud Stream消息驅(qū)動(dòng)工具使用介紹
SpringCloud Stream由一個(gè)中間件中立的核組成,應(yīng)用通過(guò)SpringCloud Stream插入的input(相當(dāng)于消費(fèi)者consumer,它是從隊(duì)列中接收消息的)和output(相當(dāng)于生產(chǎn)者producer,它是發(fā)送消息到隊(duì)列中的)通道與外界交流2022-09-09
SpringBoot-application.yml多環(huán)境配置詳解
本文主要介紹了SpringBoot-application.yml多環(huán)境配置詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
springboot config 攔截器使用方法實(shí)例詳解
本文介紹Spring-Boot中使用攔截器的相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2018-05-05

