All Downloads are FREE. Search and download functionalities are using the official Maven repository.

rpc.turbo.loadbalance.WeightableGroup Maven / Gradle / Ivy

There is a newer version: 0.0.9
Show newest version
package rpc.turbo.loadbalance;

import java.util.ArrayList;
import java.util.List;

import rpc.turbo.util.MathUtils;

/**
 * 不可变,线程安全
 * 
 * @author Hank
 *
 * @param 
 *            必须为Weightable子类
 */
public final class WeightableGroup {
	private final ArrayList weightables;
	private final int[] weightLadder;
	private final int weightSum;

	public WeightableGroup(final List weightables) {
		ArrayList weightableList = new ArrayList<>(weightables.size());

		for (T t : weightables) {
			if (t == null) {
				continue;
			}

			if (t.weight() < 1) {
				continue;
			}

			weightableList.add(t);
		}

		if (weightableList.size() == 0) {
			this.weightables = weightableList;
			this.weightLadder = new int[0];
			this.weightSum = 0;

			return;
		}

		if (weightableList.size() == 1) {
			this.weightables = weightableList;
			this.weightLadder = new int[1];
			this.weightSum = 1;

			return;
		}

		int[] weights = new int[weightableList.size()];

		for (int i = 0; i < weightableList.size(); i++) {
			weights[i] = weightableList.get(i).weight();
		}

		int gcd = MathUtils.gcd(weights);

		if (gcd > 1) {
			for (int i = 0; i < weights.length; i++) {
				weights[i] = weights[i] / gcd;
			}
		}

		for (int i = 1; i < weights.length; i++) {
			weights[i] = weights[i] + weights[i - 1];
		}

		this.weightables = weightableList;
		this.weightLadder = weights;
		this.weightSum = weights[weights.length - 1];
	}

	/**
	 * 获取weight之和,配合{@link #get(int)}使用
* *
	 * int seed = rendom.nextInt(sum());
	 * T t = get(seed);
	 * 
* * @return */ public final int sum() { return weightSum; } /** * 根据种子获取一个元素, 配合 {@link #sum()}使用
* *
	 * int seed = rendom.nextInt(sum());
	 * T t = get(seed);
	 * 
* * @param seed * @return */ public final T get(int seed) { if (weightSum == 0) { return null; } if (weightSum == 1) { return weightables.get(0); } if (seed < 0 || seed > weightSum) { seed = Math.abs(seed) % weightSum; } int index = binarySearch(weightLadder, seed); return weightables.get(index); } private static final int binarySearch(int[] values, int key) { int low = 0; int high = values.length - 1; while (low <= high) { int mid = (low + high) >>> 1; int midVal = values[mid]; if (midVal < key) { low = mid + 1; } else if (midVal > key) { high = mid - 1; } else { return mid; // key found } } return low; // key not found. } public static void main(String[] args) { int[] weightLadder = { 1, 5, 8, 15 }; int index = binarySearch(weightLadder, 15); System.out.println(index); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy