/** * Copyright (c) 2010 Yahoo! Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you * may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. See accompanying * LICENSE file. */ package com.googlecode.concurrentlinkedhashmap.generator; import java.util.Random; import java.util.Vector; /** * Generates a distribution by choosing from a discrete set of values. * * @author Brian Cooper * @see <a href="http://research.yahoo.com/Web_Information_Management/YCSB">YCSB</a> */ public class DiscreteGenerator extends Generator { class Pair { public double _weight; public String _value; Pair(double weight, String value) { _weight = weight; _value = value; } } Vector<Pair> _values; Random _random; String _lastvalue; public DiscreteGenerator() { _values = new Vector<Pair>(); _random = new Random(); _lastvalue = null; } /** * Generate the next string in the distribution. */ @Override public String nextString() { double sum = 0; for (Pair p : _values) { sum += p._weight; } double val = _random.nextDouble(); for (Pair p : _values) { if (val < p._weight / sum) { return p._value; } val -= p._weight / sum; } // should never get here. System.out.println("oops. should not get here."); System.exit(0); return null; } /** * If the generator returns numeric (integer) values, return the next value as * an int. Default is to return -1, which is appropriate for generators that * do not return numeric values. */ public int nextInt() { throw new UnsupportedOperationException("DiscreteGenerator does not support nextInt()"); } /** * Return the previous string generated by the distribution; e.g., returned * from the last nextString() call. Calling lastString() should not advance * the distribution or have any side effects. If nextString() has not yet been * called, lastString() should return something reasonable. */ @Override public String lastString() { if (_lastvalue == null) { _lastvalue = nextString(); } return _lastvalue; } public void addValue(double weight, String value) { _values.add(new Pair(weight, value)); } }