diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/lang/WeightRandom.java b/hutool-core/src/main/java/org/dromara/hutool/core/lang/WeightRandom.java
deleted file mode 100644
index 7c718893f..000000000
--- a/hutool-core/src/main/java/org/dromara/hutool/core/lang/WeightRandom.java
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (c) 2023 looly(loolly@aliyun.com)
- * Hutool is licensed under Mulan PSL v2.
- * You can use this software according to the terms and conditions of the Mulan PSL v2.
- * You may obtain a copy of Mulan PSL v2 at:
- * http://license.coscl.org.cn/MulanPSL2
- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
- * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
- * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
- * See the Mulan PSL v2 for more details.
- */
-
-package org.dromara.hutool.core.lang;
-
-import org.dromara.hutool.core.collection.CollUtil;
-import org.dromara.hutool.core.map.MapUtil;
-import org.dromara.hutool.core.util.RandomUtil;
-
-import java.io.Serializable;
-import java.util.Random;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-/**
- * 权重随机算法实现
- *
- * 平时,经常会遇到权重随机算法,从不同权重的N个元素中随机选择一个,并使得总体选择结果是按照权重分布的。如广告投放、负载均衡等。
- *
- *
- * 如有4个元素A、B、C、D,权重分别为1、2、3、4,随机结果中A:B:C:D的比例要为1:2:3:4。
- *
- * 总体思路:累加每个元素的权重A(1)-B(3)-C(6)-D(10),则4个元素的的权重管辖区间分别为[0,1)、[1,3)、[3,6)、[6,10)。
- * 然后随机出一个[0,10)之间的随机数。落在哪个区间,则该区间之后的元素即为按权重命中的元素。
- *
- *
- * 参考博客:https://www.cnblogs.com/waterystone/p/5708063.html
- *
- *
- * @param 权重随机获取的对象类型
- * @author looly
- * @since 3.3.0
- */
-public class WeightRandom implements Serializable {
- private static final long serialVersionUID = -8244697995702786499L;
-
- private final TreeMap weightMap;
-
-
- /**
- * 创建权重随机获取器
- *
- * @param 权重随机获取的对象类型
- * @return WeightRandom
- */
- public static WeightRandom of() {
- return new WeightRandom<>();
- }
-
- // ---------------------------------------------------------------------------------- Constructor start
- /**
- * 构造
- */
- public WeightRandom() {
- weightMap = new TreeMap<>();
-
- }
-
- /**
- * 构造
- *
- * @param weightObj 带有权重的对象
- */
- public WeightRandom(final WeightObj weightObj) {
- this();
- if(null != weightObj) {
- add(weightObj);
- }
- }
-
- /**
- * 构造
- *
- * @param weightObjs 带有权重的对象
- */
- public WeightRandom(final Iterable> weightObjs) {
- this();
- if(CollUtil.isNotEmpty(weightObjs)) {
- for (final WeightObj weightObj : weightObjs) {
- add(weightObj);
- }
- }
- }
-
- /**
- * 构造
- *
- * @param weightObjs 带有权重的对象
- */
- public WeightRandom(final WeightObj[] weightObjs) {
- this();
- for (final WeightObj weightObj : weightObjs) {
- add(weightObj);
- }
- }
- // ---------------------------------------------------------------------------------- Constructor end
-
- /**
- * 增加对象
- *
- * @param obj 对象
- * @param weight 权重
- * @return this
- */
- public WeightRandom add(final T obj, final double weight) {
- return add(new WeightObj<>(obj, weight));
- }
-
- /**
- * 增加对象权重
- *
- * @param weightObj 权重对象
- * @return this
- */
- public WeightRandom add(final WeightObj weightObj) {
- if(null != weightObj) {
- final double weight = weightObj.getWeight();
- if(weightObj.getWeight() > 0) {
- final double lastWeight = (this.weightMap.size() == 0) ? 0 : this.weightMap.lastKey();
- this.weightMap.put(weight + lastWeight, weightObj.getObj());// 权重累加
- }
- }
- return this;
- }
-
- /**
- * 清空权重表
- *
- * @return this
- */
- public WeightRandom clear() {
- if(null != this.weightMap) {
- this.weightMap.clear();
- }
- return this;
- }
-
- /**
- * 下一个随机对象
- *
- * @return 随机对象
- */
- public T next() {
- if(MapUtil.isEmpty(this.weightMap)) {
- return null;
- }
- final Random random = RandomUtil.getRandom();
- final double randomWeight = this.weightMap.lastKey() * random.nextDouble();
- final SortedMap tailMap = this.weightMap.tailMap(randomWeight, false);
- return this.weightMap.get(tailMap.firstKey());
- }
-
- /**
- * 带有权重的对象包装
- *
- * @author looly
- *
- * @param 对象类型
- */
- public static class WeightObj {
- /** 对象 */
- private T obj;
- /** 权重 */
- private final double weight;
-
- /**
- * 构造
- *
- * @param obj 对象
- * @param weight 权重
- */
- public WeightObj(final T obj, final double weight) {
- this.obj = obj;
- this.weight = weight;
- }
-
- /**
- * 获取对象
- *
- * @return 对象
- */
- public T getObj() {
- return obj;
- }
-
- /**
- * 设置对象
- *
- * @param obj 对象
- */
- public void setObj(final T obj) {
- this.obj = obj;
- }
-
- /**
- * 获取权重
- *
- * @return 权重
- */
- public double getWeight() {
- return weight;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((obj == null) ? 0 : obj.hashCode());
- final long temp;
- temp = Double.doubleToLongBits(weight);
- result = prime * result + (int) (temp ^ (temp >>> 32));
- return result;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- final WeightObj> other = (WeightObj>) obj;
- if (this.obj == null) {
- if (other.obj != null) {
- return false;
- }
- } else if (!this.obj.equals(other.obj)) {
- return false;
- }
- return Double.doubleToLongBits(weight) == Double.doubleToLongBits(other.weight);
- }
- }
-
-}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/lang/selector/Selector.java b/hutool-core/src/main/java/org/dromara/hutool/core/lang/selector/Selector.java
new file mode 100644
index 000000000..295e2871c
--- /dev/null
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/lang/selector/Selector.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2023 looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+package org.dromara.hutool.core.lang.selector;
+
+/**
+ * 选择器接口
+ *
+ * @param 选择对象类型
+ * @author looly
+ * @since 6.0.0
+ */
+public interface Selector {
+
+ /**
+ * 选择下一个对象
+ *
+ * @return 下一个对象
+ */
+ T next();
+}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/lang/selector/SmoothWeightObj.java b/hutool-core/src/main/java/org/dromara/hutool/core/lang/selector/SmoothWeightObj.java
new file mode 100644
index 000000000..d8384008e
--- /dev/null
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/lang/selector/SmoothWeightObj.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2023 looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+package org.dromara.hutool.core.lang.selector;
+
+/**
+ * 平滑权重对象
+ *
+ * @param 对象类型
+ * @author Wind, Loolt
+ */
+public class SmoothWeightObj extends WeightObj {
+
+ private int currentWeight;
+
+ /**
+ * 构造
+ *
+ * @param obj 对象
+ * @param weight 权重
+ */
+ public SmoothWeightObj(final T obj, final int weight) {
+ this(obj, weight, 0);
+ }
+
+ /**
+ * 构造
+ *
+ * @param obj 对象
+ * @param weight 权重
+ * @param currentWeight 当前权重
+ */
+ public SmoothWeightObj(final T obj, final int weight, final int currentWeight) {
+ super(obj, weight);
+ this.currentWeight = currentWeight;
+ }
+
+ /**
+ * 获取当前权重
+ *
+ * @return int 临时权重
+ */
+ public int getCurrentWeight() {
+ return currentWeight;
+ }
+
+ /**
+ * setCurrentWeight
+ * 设置当前权重
+ *
+ * @param currentWeight 权重值
+ */
+ public void setCurrentWeight(final int currentWeight) {
+ this.currentWeight = currentWeight;
+ }
+}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/lang/selector/SmoothWeightSelector.java b/hutool-core/src/main/java/org/dromara/hutool/core/lang/selector/SmoothWeightSelector.java
new file mode 100644
index 000000000..bb7933341
--- /dev/null
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/lang/selector/SmoothWeightSelector.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2023 looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+package org.dromara.hutool.core.lang.selector;
+
+import org.dromara.hutool.core.collection.CollUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 平滑加权轮询选择器
+ *
+ *
+ * 来自:https://gitee.com/dromara/hutool/pulls/982/
+ *
+ *
+ * 介绍:https://cloud.tencent.com/developer/beta/article/1680928
+ *
+ *
+ *
+ * 思路: 比如 A : 5 , B : 3 , C : 2 (服务器 A,B,C 对应权重分别是 5,3,2)
+ * ip: A,B,C
+ * weight: 5,3,2 (计算得到 totalWeight = 10)
+ * currentWeight: 0,0,0 (当前ip的初始权重都为0)
+ *
+ * 请求次数: | currentWeight = currentWeight + weight | 最大权重为 | 返回的ip为 | 最大的权重 - totalWeight,其余不变
+ * 1 | 5,3,2 (0,0,0 + 5,3,2) | 5 | A | -5,3,2
+ * 2 | 0,6,4 (-5,3,2 + 5,3,2) | 6 | B | 0,-4,4
+ * 3 | 5,-1,6 (0,-4,4 + 5,3,2) | 6 | C | 5,-1,-4
+ * 4 | 10,2,-2 (5,-1,-4 + 5,3,2) | 10 | A | 0,2,-2
+ * 5 | 5,5,0 | 5 | A | -5,5,0
+ * 6 | 0,8,2 | 8 | B | 0,-2,2
+ * 7 | 5,1,4 | 5 | A | -5,1,4
+ * 8 | 0,4,6 | 6 | C | 0,4,-4
+ * 9 | 5,7,-2 | 7 | B | 5,-3,-2
+ * 10 | 10,0,0 | 10 | A | 0,0,0
+ *
+ *
+ * 至此结束: 可以看到负载轮询的策略是: A,B,C,A,A,B,A,C,B,A,
+ *
+ * @param 对象类型
+ * @author :Wind, Looly
+ */
+public class SmoothWeightSelector implements Selector {
+
+ /**
+ * 创建平滑加权获取器
+ *
+ * @param 对象类型
+ * @return SmoothSelector
+ */
+ public static SmoothWeightSelector of() {
+ return new SmoothWeightSelector<>();
+ }
+
+ private final List> objList;
+
+ // region ----- Constructors
+
+ /**
+ * 构造
+ */
+ public SmoothWeightSelector() {
+ this.objList = new ArrayList<>();
+ }
+
+ /**
+ * 构造
+ *
+ * @param weightObjList 权重对象列表
+ */
+ public SmoothWeightSelector(final Iterable extends WeightObj> weightObjList) {
+ this();
+ for (final WeightObj weightObj : weightObjList) {
+ add(weightObj);
+ }
+ }
+ // endregion
+
+ /**
+ * 增加对象
+ *
+ * @param obj 对象
+ * @param weight 权重
+ * @return this
+ */
+ public SmoothWeightSelector add(final T obj, final int weight) {
+ return add(new SmoothWeightObj<>(obj, weight));
+ }
+
+ /**
+ * 增加权重对象
+ *
+ * @param weightObj 权重对象
+ * @return this
+ */
+ public SmoothWeightSelector add(final WeightObj weightObj) {
+ final SmoothWeightObj smoothWeightObj;
+ if (weightObj instanceof SmoothWeightObj) {
+ smoothWeightObj = (SmoothWeightObj) weightObj;
+ } else {
+ smoothWeightObj = new SmoothWeightObj<>(weightObj.obj, weightObj.weight);
+ }
+ this.objList.add(smoothWeightObj);
+ return this;
+ }
+
+ /**
+ * 通过平滑加权方法获取列表中的当前对象
+ *
+ * @return 选中的对象
+ */
+ @Override
+ public T next() {
+ if (CollUtil.isEmpty(this.objList)) {
+ return null;
+ }
+ int totalWeight = 0;
+ SmoothWeightObj selected = null;
+
+ for (final SmoothWeightObj obj : objList) {
+ totalWeight += obj.getWeight();
+ final int currentWeight = obj.getCurrentWeight() + obj.getWeight();
+ obj.setCurrentWeight(currentWeight);
+ if (null == selected || currentWeight > selected.getCurrentWeight()) {
+ selected = obj;
+ }
+ }
+
+ if (null == selected) {
+ return null;
+ }
+
+ // 更新选择的对象的当前权重,并返回其地址
+ selected.setCurrentWeight(selected.getCurrentWeight() - totalWeight);
+
+ return selected.getObj();
+ }
+}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/lang/selector/WeightObj.java b/hutool-core/src/main/java/org/dromara/hutool/core/lang/selector/WeightObj.java
new file mode 100644
index 000000000..0a4bf840d
--- /dev/null
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/lang/selector/WeightObj.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2023 looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+package org.dromara.hutool.core.lang.selector;
+
+import java.util.Objects;
+
+/**
+ * 带有权重的对象包装
+ *
+ * @author looly
+ *
+ * @param 对象类型
+ */
+public class WeightObj {
+ /** 对象 */
+ protected T obj;
+ /** 权重 */
+ protected final int weight;
+
+ /**
+ * 构造
+ *
+ * @param obj 对象
+ * @param weight 权重
+ */
+ public WeightObj(final T obj, final int weight) {
+ this.obj = obj;
+ this.weight = weight;
+ }
+
+ /**
+ * 获取对象
+ *
+ * @return 对象
+ */
+ public T getObj() {
+ return obj;
+ }
+
+ /**
+ * 设置对象
+ *
+ * @param obj 对象
+ */
+ public void setObj(final T obj) {
+ this.obj = obj;
+ }
+
+ /**
+ * 获取权重
+ *
+ * @return 权重
+ */
+ public int getWeight() {
+ return weight;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ final WeightObj> weightObj = (WeightObj>) o;
+ return weight == weightObj.weight && Objects.equals(obj, weightObj.obj);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(obj, weight);
+ }
+}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/lang/selector/WeightRandomSelector.java b/hutool-core/src/main/java/org/dromara/hutool/core/lang/selector/WeightRandomSelector.java
new file mode 100644
index 000000000..215918b00
--- /dev/null
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/lang/selector/WeightRandomSelector.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2023 looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+package org.dromara.hutool.core.lang.selector;
+
+import org.dromara.hutool.core.collection.CollUtil;
+
+import java.io.Serializable;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+/**
+ * 权重随机选择算法实现
+ *
+ * 平时,经常会遇到权重随机算法,从不同权重的N个元素中随机选择一个,并使得总体选择结果是按照权重分布的。如广告投放、负载均衡等。
+ *
+ *
+ * 如有4个元素A、B、C、D,权重分别为1、2、3、4,随机结果中A:B:C:D的比例要为1:2:3:4。
+ *
+ * 总体思路:累加每个元素的权重A(1)-B(3)-C(6)-D(10),则4个元素的的权重管辖区间分别为[0,1)、[1,3)、[3,6)、[6,10)。
+ * 然后随机出一个[0,10)之间的随机数。落在哪个区间,则该区间之后的元素即为按权重命中的元素。
+ *
+ *
+ * 参考博客:https://www.cnblogs.com/waterystone/p/5708063.html
+ *
+ * @param 权重随机获取的对象类型
+ * @author looly
+ * @since 3.3.0
+ */
+public class WeightRandomSelector implements Selector, Serializable {
+ private static final long serialVersionUID = -8244697995702786499L;
+
+ /**
+ * 创建权重随机获取器
+ *
+ * @param 权重随机获取的对象类型
+ * @return WeightRandomSelector
+ */
+ public static WeightRandomSelector of() {
+ return new WeightRandomSelector<>();
+ }
+
+ private final TreeMap weightMap;
+
+ // region ----- Constructors
+
+ /**
+ * 构造
+ */
+ public WeightRandomSelector() {
+ weightMap = new TreeMap<>();
+ }
+
+ /**
+ * 构造
+ *
+ * @param weightObj 带有权重的对象
+ */
+ public WeightRandomSelector(final WeightObj weightObj) {
+ this();
+ if (null != weightObj) {
+ add(weightObj);
+ }
+ }
+
+ /**
+ * 构造
+ *
+ * @param weightObjs 带有权重的对象
+ */
+ public WeightRandomSelector(final Iterable> weightObjs) {
+ this();
+ if (CollUtil.isNotEmpty(weightObjs)) {
+ for (final WeightObj weightObj : weightObjs) {
+ add(weightObj);
+ }
+ }
+ }
+
+ /**
+ * 构造
+ *
+ * @param weightObjs 带有权重的对象
+ */
+ public WeightRandomSelector(final WeightObj[] weightObjs) {
+ this();
+ for (final WeightObj weightObj : weightObjs) {
+ add(weightObj);
+ }
+ }
+ // endregion
+
+ /**
+ * 增加对象
+ *
+ * @param obj 对象
+ * @param weight 权重
+ * @return this
+ */
+ public WeightRandomSelector add(final T obj, final int weight) {
+ return add(new WeightObj<>(obj, weight));
+ }
+
+ /**
+ * 增加对象权重
+ *
+ * @param weightObj 权重对象
+ * @return this
+ */
+ public WeightRandomSelector add(final WeightObj weightObj) {
+ if (null != weightObj) {
+ final int weight = weightObj.getWeight();
+ if (weight > 0) {
+ final int lastWeight = this.weightMap.isEmpty() ? 0 : this.weightMap.lastKey();
+ this.weightMap.put(weight + lastWeight, weightObj.getObj());// 权重累加
+ }
+ }
+ return this;
+ }
+
+ /**
+ * 清空权重表
+ *
+ * @return this
+ */
+ public WeightRandomSelector clear() {
+ if (null != this.weightMap) {
+ this.weightMap.clear();
+ }
+ return this;
+ }
+
+ /**
+ * 下一个随机对象
+ *
+ * @return 随机对象
+ */
+ @Override
+ public T next() {
+ final int randomWeight = (int) (this.weightMap.lastKey() * Math.random());
+ final SortedMap tailMap = this.weightMap.tailMap(randomWeight, false);
+ return this.weightMap.get(tailMap.firstKey());
+ }
+}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/lang/selector/package-info.java b/hutool-core/src/main/java/org/dromara/hutool/core/lang/selector/package-info.java
new file mode 100644
index 000000000..b15cd29df
--- /dev/null
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/lang/selector/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2023 looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+/**
+ * 选择器相关封装,包括:
+ *
+ * - {@link org.dromara.hutool.core.lang.selector.WeightRandomSelector}
+ *
+ *
+ * @author looly
+ */
+package org.dromara.hutool.core.lang.selector;
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/map/concurrent/ConcurrentLinkedHashMap.java b/hutool-core/src/main/java/org/dromara/hutool/core/map/concurrent/ConcurrentLinkedHashMap.java
index 71df73fd4..fa42d9f8b 100755
--- a/hutool-core/src/main/java/org/dromara/hutool/core/map/concurrent/ConcurrentLinkedHashMap.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/map/concurrent/ConcurrentLinkedHashMap.java
@@ -40,18 +40,18 @@ import java.util.function.BiConsumer;
* concurrency for updates, and a maximum capacity to bound the map by. This
* implementation differs from {@link ConcurrentHashMap} in that it maintains a
* page replacement algorithm that is used to evict an entry when the map has
- * exceeded its capacity. Unlike the Java Collections Framework, this
+ * exceeded its capacity. Unlike the {@code Java Collections Framework}, this
* map does not have a publicly visible constructor and instances are created
* through a {@link Builder}.
*
- * An entry is evicted from the map when the weighted capacity exceeds
- * its maximum weighted capacity threshold. A {@link EntryWeigher}
+ * An entry is evicted from the map when the {@code weighted capacity} exceeds
+ * its {@code maximum weighted capacity} threshold. A {@link EntryWeigher}
* determines how many units of capacity that an entry consumes. The default
- * weigher assigns each value a weight of 1 to bound the map by the
+ * weigher assigns each value a selector of {@code 1} to bound the map by the
* total number of key-value pairs. A map that holds collections may choose to
* weigh values by the number of elements in the collection and bound the map
* by the total number of elements that it contains. A change to a value that
- * modifies its weight requires that an update operation is performed on the
+ * modifies its selector requires that an update operation is performed on the
* map.
*
* An {@link BiConsumer} may be supplied for notification when an entry
@@ -63,7 +63,7 @@ import java.util.function.BiConsumer;
* operation asynchronously, such as by submitting a task to an
* {@link java.util.concurrent.ExecutorService}.
*
- * The concurrency level determines the number of threads that can
+ * The {@code concurrency level} determines the number of threads that can
* concurrently modify the table. Using a significantly higher or lower value
* than needed can waste space or lead to thread contention, but an estimate
* within an order of magnitude of the ideal value does not usually have a
@@ -75,7 +75,7 @@ import java.util.function.BiConsumer;
* interfaces.
*
* Like {@link Hashtable} but unlike {@link HashMap}, this class
- * does not allow null to be used as a key or value. Unlike
+ * does not allow {@code null} to be used as a key or value. Unlike
* {@link LinkedHashMap}, this class does not provide
* predictable iteration order. A snapshot of the keys and entries may be
* obtained in ascending and descending order of retention.
@@ -112,16 +112,16 @@ public final class ConcurrentLinkedHashMap extends AbstractMap
*
* Due to a lack of a strict ordering guarantee, a task can be executed
* out-of-order, such as a removal followed by its addition. The state of the
- * entry is encoded within the value's weight.
+ * entry is encoded within the value's selector.
*
* Alive: The entry is in both the hash-table and the page replacement policy.
- * This is represented by a positive weight.
+ * This is represented by a positive selector.
*
* Retired: The entry is not in the hash-table and is pending removal from the
- * page replacement policy. This is represented by a negative weight.
+ * page replacement policy. This is represented by a negative selector.
*
* Dead: The entry is not in the hash-table and is not in the page replacement
- * policy. This is represented by a weight of zero.
+ * policy. This is represented by a selector of zero.
*
* The Least Recently Used page replacement algorithm was chosen due to its
* simplicity, high hit rate, and ability to be implemented with O(1) time
@@ -297,7 +297,7 @@ public final class ConcurrentLinkedHashMap extends AbstractMap
final Node node = evictionDeque.poll();
// If weighted values are used, then the pending operations will adjust
- // the size to reflect the correct weight
+ // the size to reflect the correct selector
if (node == null) {
return;
}
@@ -466,8 +466,8 @@ public final class ConcurrentLinkedHashMap extends AbstractMap
}
/**
- * Attempts to transition the node from the alive state to the
- * retired state.
+ * Attempts to transition the node from the {@code alive} state to the
+ * {@code retired} state.
*
* @param node the entry in the page replacement policy
* @param expect the expected weighted value
@@ -482,8 +482,8 @@ public final class ConcurrentLinkedHashMap extends AbstractMap
}
/**
- * Atomically transitions the node from the alive state to the
- * retired state, if a valid transition.
+ * Atomically transitions the node from the {@code alive} state to the
+ * {@code retired} state, if a valid transition.
*
* @param node the entry in the page replacement policy
*/
@@ -501,8 +501,8 @@ public final class ConcurrentLinkedHashMap extends AbstractMap
}
/**
- * Atomically transitions the node to the dead state and decrements
- * the weightedSize.
+ * Atomically transitions the node to the {@code dead} state and decrements
+ * the {@code weightedSize}.
*
* @param node the entry in the page replacement policy
*/
@@ -608,7 +608,7 @@ public final class ConcurrentLinkedHashMap extends AbstractMap
/**
* Returns the weighted size of this map.
*
- * @return the combined weight of the values in this map
+ * @return the combined selector of the values in this map
*/
public long weightedSize() {
return Math.max(0, weightedSize.get());
@@ -1097,7 +1097,7 @@ public final class ConcurrentLinkedHashMap extends AbstractMap
}
/**
- * A value, its weight, and the entry's status.
+ * A value, its selector, and the entry's status.
*/
static final class WeightedValue {
final int weight;
@@ -1178,7 +1178,7 @@ public final class ConcurrentLinkedHashMap extends AbstractMap
}
/**
- * Retrieves the value held by the current WeightedValue.
+ * Retrieves the value held by the current {@code WeightedValue}.
*/
V getValue() {
return get().value;
@@ -1401,7 +1401,7 @@ public final class ConcurrentLinkedHashMap extends AbstractMap
}
/**
- * A weigher that enforces that the weight falls within a valid range.
+ * A weigher that enforces that the selector falls within a valid range.
*/
static final class BoundedEntryWeigher implements EntryWeigher, Serializable {
private static final long serialVersionUID = 1;
@@ -1520,7 +1520,7 @@ public final class ConcurrentLinkedHashMap extends AbstractMap
}
/**
- * Specifies the initial capacity of the hash table (default 16).
+ * Specifies the initial capacity of the hash table (default {@code 16}).
* This is the number of key-value pairs that the hash table can hold
* before a resize operation is required.
*
@@ -1553,7 +1553,7 @@ public final class ConcurrentLinkedHashMap extends AbstractMap
/**
* Specifies the estimated number of concurrently updating threads. The
* implementation performs internal sizing to try to accommodate this many
- * threads (default 16).
+ * threads (default {@code 16}).
*
* @param concurrencyLevel the estimated number of concurrently updating
* threads
@@ -1584,9 +1584,9 @@ public final class ConcurrentLinkedHashMap extends AbstractMap
/**
* Specifies an algorithm to determine how many the units of capacity a
* value consumes. The default algorithm bounds the map by the number of
- * key-value pairs by giving each entry a weight of 1.
+ * key-value pairs by giving each entry a selector of {@code 1}.
*
- * @param weigher the algorithm to determine a value's weight
+ * @param weigher the algorithm to determine a value's selector
* @return this
* @throws NullPointerException if the weigher is null
*/
@@ -1600,9 +1600,9 @@ public final class ConcurrentLinkedHashMap extends AbstractMap
/**
* Specifies an algorithm to determine how many the units of capacity an
* entry consumes. The default algorithm bounds the map by the number of
- * key-value pairs by giving each entry a weight of 1.
+ * key-value pairs by giving each entry a selector of {@code 1}.
*
- * @param weigher the algorithm to determine a entry's weight
+ * @param weigher the algorithm to determine a entry's selector
* @return this
* @throws NullPointerException if the weigher is null
*/
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/map/concurrent/EntryWeigher.java b/hutool-core/src/main/java/org/dromara/hutool/core/map/concurrent/EntryWeigher.java
index 18d6eab2d..14f78699e 100755
--- a/hutool-core/src/main/java/org/dromara/hutool/core/map/concurrent/EntryWeigher.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/map/concurrent/EntryWeigher.java
@@ -16,7 +16,7 @@
package org.dromara.hutool.core.map.concurrent;
/**
- * A class that can determine the weight of an entry. The total weight threshold
+ * A class that can determine the selector of an entry. The total selector threshold
* is used to determine when an eviction is required.
*
* @param 键类型
@@ -28,12 +28,12 @@ package org.dromara.hutool.core.map.concurrent;
public interface EntryWeigher {
/**
- * Measures an entry's weight to determine how many units of capacity that
+ * Measures an entry's selector to determine how many units of capacity that
* the key and value consumes. An entry must consume a minimum of one unit.
*
* @param key the key to weigh
* @param value the value to weigh
- * @return the entry's weight
+ * @return the entry's selector
*/
int weightOf(K key, V value);
}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/map/concurrent/Weigher.java b/hutool-core/src/main/java/org/dromara/hutool/core/map/concurrent/Weigher.java
index d2b28e3e6..bd54810f7 100755
--- a/hutool-core/src/main/java/org/dromara/hutool/core/map/concurrent/Weigher.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/map/concurrent/Weigher.java
@@ -16,7 +16,7 @@
package org.dromara.hutool.core.map.concurrent;
/**
- * A class that can determine the weight of a value. The total weight threshold
+ * A class that can determine the selector of a value. The total selector threshold
* is used to determine when an eviction is required.
*
* @param 值类型
@@ -27,11 +27,11 @@ package org.dromara.hutool.core.map.concurrent;
public interface Weigher {
/**
- * Measures an object's weight to determine how many units of capacity that
+ * Measures an object's selector to determine how many units of capacity that
* the value consumes. A value must consume a minimum of one unit.
*
* @param value the object to weigh
- * @return the object's weight
+ * @return the object's selector
*/
int weightOf(V value);
}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/map/concurrent/Weighers.java b/hutool-core/src/main/java/org/dromara/hutool/core/map/concurrent/Weighers.java
index 45ad245b9..0949b586a 100755
--- a/hutool-core/src/main/java/org/dromara/hutool/core/map/concurrent/Weighers.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/map/concurrent/Weighers.java
@@ -38,8 +38,8 @@ public final class Weighers {
}
/**
- * A entry weigher backed by the specified weigher. The weight of the value
- * determines the weight of the entry.
+ * A entry weigher backed by the specified weigher. The selector of the value
+ * determines the selector of the entry.
*
* @param weigher the weigher to be "wrapped" in a entry weigher.
* @param 键类型
@@ -54,7 +54,7 @@ public final class Weighers {
}
/**
- * A weigher where an entry has a weight of 1. A map bounded with
+ * A weigher where an entry has a selector of 1. A map bounded with
* this weigher will evict when the number of key-value pairs exceeds the
* capacity.
*
@@ -68,7 +68,7 @@ public final class Weighers {
}
/**
- * A weigher where a value has a weight of 1. A map bounded with
+ * A weigher where a value has a selector of 1. A map bounded with
* this weigher will evict when the number of key-value pairs exceeds the
* capacity.
*
@@ -81,17 +81,17 @@ public final class Weighers {
}
/**
- * A weigher where the value is a byte array and its weight is the number of
+ * A weigher where the value is a byte array and its selector is the number of
* bytes. A map bounded with this weigher will evict when the number of bytes
* exceeds the capacity rather than the number of key-value pairs in the map.
* This allows for restricting the capacity based on the memory-consumption
* and is primarily for usage by dedicated caching servers that hold the
* serialized data.
*
- * A value with a weight of 0 will be rejected by the map. If a value
- * with this weight can occur then the caller should eagerly evaluate the
+ * A value with a selector of 0 will be rejected by the map. If a value
+ * with this selector can occur then the caller should eagerly evaluate the
* value and treat it as a removal operation. Alternatively, a custom weigher
- * may be specified on the map to assign an empty value a positive weight.
+ * may be specified on the map to assign an empty value a positive selector.
*
* @return A weigher where each byte takes one unit of capacity.
*/
@@ -100,16 +100,16 @@ public final class Weighers {
}
/**
- * A weigher where the value is a {@link Iterable} and its weight is the
+ * A weigher where the value is a {@link Iterable} and its selector is the
* number of elements. This weigher only should be used when the alternative
* {@link #collection()} weigher cannot be, as evaluation takes O(n) time. A
* map bounded with this weigher will evict when the total number of elements
* exceeds the capacity rather than the number of key-value pairs in the map.
*
- * A value with a weight of 0 will be rejected by the map. If a value
- * with this weight can occur then the caller should eagerly evaluate the
+ * A value with a selector of 0 will be rejected by the map. If a value
+ * with this selector can occur then the caller should eagerly evaluate the
* value and treat it as a removal operation. Alternatively, a custom weigher
- * may be specified on the map to assign an empty value a positive weight.
+ * may be specified on the map to assign an empty value a positive selector.
*
* @param 元素类型
* @return A weigher where each element takes one unit of capacity.
@@ -120,15 +120,15 @@ public final class Weighers {
}
/**
- * A weigher where the value is a {@link Collection} and its weight is the
+ * A weigher where the value is a {@link Collection} and its selector is the
* number of elements. A map bounded with this weigher will evict when the
* total number of elements exceeds the capacity rather than the number of
* key-value pairs in the map.
*
- * A value with a weight of 0 will be rejected by the map. If a value
- * with this weight can occur then the caller should eagerly evaluate the
+ * A value with a selector of 0 will be rejected by the map. If a value
+ * with this selector can occur then the caller should eagerly evaluate the
* value and treat it as a removal operation. Alternatively, a custom weigher
- * may be specified on the map to assign an empty value a positive weight.
+ * may be specified on the map to assign an empty value a positive selector.
*
* @param 元素类型
* @return A weigher where each element takes one unit of capacity.
@@ -139,15 +139,15 @@ public final class Weighers {
}
/**
- * A weigher where the value is a {@link List} and its weight is the number
+ * A weigher where the value is a {@link List} and its selector is the number
* of elements. A map bounded with this weigher will evict when the total
* number of elements exceeds the capacity rather than the number of
* key-value pairs in the map.
*
- * A value with a weight of 0 will be rejected by the map. If a value
- * with this weight can occur then the caller should eagerly evaluate the
+ * A value with a selector of 0 will be rejected by the map. If a value
+ * with this selector can occur then the caller should eagerly evaluate the
* value and treat it as a removal operation. Alternatively, a custom weigher
- * may be specified on the map to assign an empty value a positive weight.
+ * may be specified on the map to assign an empty value a positive selector.
*
* @param 元素类型
* @return A weigher where each element takes one unit of capacity.
@@ -158,15 +158,15 @@ public final class Weighers {
}
/**
- * A weigher where the value is a {@link Set} and its weight is the number
+ * A weigher where the value is a {@link Set} and its selector is the number
* of elements. A map bounded with this weigher will evict when the total
* number of elements exceeds the capacity rather than the number of
* key-value pairs in the map.
*
- * A value with a weight of 0 will be rejected by the map. If a value
- * with this weight can occur then the caller should eagerly evaluate the
+ * A value with a selector of 0 will be rejected by the map. If a value
+ * with this selector can occur then the caller should eagerly evaluate the
* value and treat it as a removal operation. Alternatively, a custom weigher
- * may be specified on the map to assign an empty value a positive weight.
+ * may be specified on the map to assign an empty value a positive selector.
*
* @param 元素类型
* @return A weigher where each element takes one unit of capacity.
@@ -177,15 +177,15 @@ public final class Weighers {
}
/**
- * A weigher where the value is a {@link Map} and its weight is the number of
+ * A weigher where the value is a {@link Map} and its selector is the number of
* entries. A map bounded with this weigher will evict when the total number of
* entries across all values exceeds the capacity rather than the number of
* key-value pairs in the map.
*
- * A value with a weight of 0 will be rejected by the map. If a value
- * with this weight can occur then the caller should eagerly evaluate the
+ * A value with a selector of 0 will be rejected by the map. If a value
+ * with this selector can occur then the caller should eagerly evaluate the
* value and treat it as a removal operation. Alternatively, a custom weigher
- * may be specified on the map to assign an empty value a positive weight.
+ * may be specified on the map to assign an empty value a positive selector.
*
* @param 键类型
* @param 值类型
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/tree/TreeNodeConfig.java b/hutool-core/src/main/java/org/dromara/hutool/core/tree/TreeNodeConfig.java
index aa100ed78..04dc9dc41 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/tree/TreeNodeConfig.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/tree/TreeNodeConfig.java
@@ -30,7 +30,7 @@ public class TreeNodeConfig implements Serializable {
// 属性名配置字段
private String idKey = "id";
private String parentIdKey = "parentId";
- private String weightKey = "weight";
+ private String weightKey = "selector";
private String nameKey = "name";
private String childrenKey = "children";
// 可以配置递归深度 从0开始计算 默认此配置为空,即不限制
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/util/RandomUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/util/RandomUtil.java
index 9d2f6fa89..6031cd469 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/util/RandomUtil.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/util/RandomUtil.java
@@ -20,8 +20,8 @@ import org.dromara.hutool.core.date.DateTime;
import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.exception.HutoolException;
import org.dromara.hutool.core.lang.Assert;
-import org.dromara.hutool.core.lang.WeightRandom;
-import org.dromara.hutool.core.lang.WeightRandom.WeightObj;
+import org.dromara.hutool.core.lang.selector.WeightObj;
+import org.dromara.hutool.core.lang.selector.WeightRandomSelector;
import org.dromara.hutool.core.math.NumberUtil;
import org.dromara.hutool.core.text.StrUtil;
@@ -29,13 +29,7 @@ import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Random;
-import java.util.Set;
+import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
/**
@@ -637,11 +631,11 @@ public class RandomUtil {
*
* @param 随机对象类型
* @param weightObjs 带有权重的对象列表
- * @return {@link WeightRandom}
+ * @return {@link WeightRandomSelector}
* @since 4.0.3
*/
- public static WeightRandom weightRandom(final WeightObj[] weightObjs) {
- return new WeightRandom<>(weightObjs);
+ public static WeightRandomSelector weightRandom(final WeightObj[] weightObjs) {
+ return new WeightRandomSelector<>(weightObjs);
}
/**
@@ -649,11 +643,11 @@ public class RandomUtil {
*
* @param 随机对象类型
* @param weightObjs 带有权重的对象列表
- * @return {@link WeightRandom}
+ * @return {@link WeightRandomSelector}
* @since 4.0.3
*/
- public static WeightRandom weightRandom(final Iterable> weightObjs) {
- return new WeightRandom<>(weightObjs);
+ public static WeightRandomSelector weightRandom(final Iterable> weightObjs) {
+ return new WeightRandomSelector<>(weightObjs);
}
/**
diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/lang/WeightRandomTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/lang/WeightRandomTest.java
deleted file mode 100644
index 9ce168f1f..000000000
--- a/hutool-core/src/test/java/org/dromara/hutool/core/lang/WeightRandomTest.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.dromara.hutool.core.lang;
-
-import org.dromara.hutool.core.collection.ListUtil;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-public class WeightRandomTest {
-
- @Test
- public void weightRandomTest() {
- final WeightRandom random = WeightRandom.of();
- random.add("A", 10);
- random.add("B", 50);
- random.add("C", 100);
-
- final String result = random.next();
- Assertions.assertTrue(ListUtil.of("A", "B", "C").contains(result));
- }
-}
diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/lang/selector/WeightRandomSelectorTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/lang/selector/WeightRandomSelectorTest.java
new file mode 100644
index 000000000..3ad880540
--- /dev/null
+++ b/hutool-core/src/test/java/org/dromara/hutool/core/lang/selector/WeightRandomSelectorTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2023 looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+package org.dromara.hutool.core.lang.selector;
+
+import org.dromara.hutool.core.collection.ListUtil;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class WeightRandomSelectorTest {
+
+ @Test
+ public void weightRandomTest() {
+ final WeightRandomSelector random = WeightRandomSelector.of();
+ random.add("A", 10);
+ random.add("B", 50);
+ random.add("C", 100);
+
+ final String result = random.next();
+ Assertions.assertTrue(ListUtil.of("A", "B", "C").contains(result));
+ }
+}