package edu.uw.zookeeper.client.random; import static com.google.common.base.Preconditions.checkArgument; import java.util.Arrays; import java.util.Random; import com.google.common.collect.ImmutableRangeMap; import com.google.common.collect.Range; import com.google.common.primitives.Floats; import edu.uw.zookeeper.common.AbstractPair; import edu.uw.zookeeper.common.Generator; import edu.uw.zookeeper.common.Pair; public final class BinGenerator<V> extends AbstractPair<Random, ImmutableRangeMap<Float, V>> implements Generator<V> { public static <V> BinGenerator<V> create( Random random, Pair<Float, ? extends V>...weightedValues) { return create(random, Arrays.asList(weightedValues)); } public static <V> BinGenerator<V> create( Random random, Iterable<? extends Pair<Float, ? extends V>> weightedValues) { final ImmutableRangeMap.Builder<Float, V> bins = ImmutableRangeMap.builder(); Float lower = Float.valueOf(0.0f); for (Pair<Float, ? extends V> weightedValue: weightedValues) { if (weightedValue.first().floatValue() <= 0.0f) { continue; } Float upper = Float.valueOf(Floats.min(1.0f, lower.floatValue() + weightedValue.first().floatValue())); checkArgument(upper.floatValue() > lower.floatValue()); Range<Float> range = Range.closedOpen(lower, upper); bins.put(range, weightedValue.second()); lower = upper; } checkArgument(Float.compare(lower.floatValue(), 1.0f) == 0); return new BinGenerator<V>(random, bins.build()); } protected BinGenerator(Random random, ImmutableRangeMap<Float, V> bins) { super(random, bins); } public Random getRandom() { return first; } public ImmutableRangeMap<Float, V> getBins() { return second; } @Override public V next() { final float next = getRandom().nextFloat(); return getBins().get(Float.valueOf(next)); } }