High-performance, battle-tested weighted random sampling library for JVM
Weighted Lottery is a collection of optimized algorithms for weighted random sampling (also known as weighted random selection or probability-based selection). Choose items randomly according to their assigned probabilities, with or without replacement.
- π Multiple optimized algorithms - Choose the best one for your use case
- β‘ High performance - Extensively benchmarked with JMH
- π§ Flexible - Supports sampling with and without replacement
- π Battle-tested - Used in production systems
- π― Type-safe - Written in Kotlin with Java interoperability
- ποΈ Zero dependencies - Lightweight and self-contained
<dependency>
<groupId>io.github.guyko</groupId>
<artifactId>WeightedLottery</artifactId>
<version>1.0.2</version>
</dependency>
implementation("io.github.guyko:WeightedLottery:1.0.2")
// Define weights for 5 items
val weights = doubleArrayOf(0.15, 0.0, 0.2, 0.0, 0.65)
val lottery = SimpleIntWeightedLottery(weights)
// Draw 10 samples (with replacement)
repeat(10) {
val selectedIndex = lottery.draw()
println("Selected item at index: $selectedIndex")
}
val weights = doubleArrayOf(0.3, 0.2, 0.5)
val lottery = SimpleIntWeightedLotteryNoRepetitions(weights)
// Draw all items until exhausted
while (!lottery.empty()) {
val selectedIndex = lottery.draw()
println("Selected: $selectedIndex, remaining: ${lottery.remaining()}")
}
- A/B Testing - Route users to experiments based on traffic allocation
- Load Balancing - Distribute requests across servers by capacity
- Game Development - Item drops, character selection, procedural generation
- Recommendation Systems - Sample items based on relevance scores
- Monte Carlo Simulations - Weighted random sampling in statistical models
All implementations are rigorously benchmarked using JMH. Choose the best algorithm for your specific use case:
π Interactive Benchmark Results
Algorithm | Best For | Time Complexity | Space Complexity |
---|---|---|---|
SimpleIntWeightedLottery |
Small datasets, simple use cases | O(n) | O(n) |
AliasLottery |
Large datasets, frequent sampling | O(1) | O(n) |
SumTreeLottery |
Dynamic weights, frequent updates | O(log n) | O(n) |
ReservoirLottery |
Sampling without replacement | O(k) | O(k) |
SimpleIntWeightedLottery
- Binary search on cumulative weightsAliasLottery
- Walker's alias method for O(1) samplingTwistedAliasLottery
- Optimized alias method variantSumTreeLottery
- Binary tree for dynamic weight updatesUniformLottery
- Uniform distribution (all weights equal)
SimpleIntWeightedLotteryNoRepetitions
- Removes selected itemsAliasLotteryNoRepetitions
- Alias method with item removalReservoirLottery
- Reservoir sampling algorithm
val lottery = SimpleIntWeightedLottery(
weights = weights,
random = { ThreadLocalRandom.current() }
)
try {
val index = lottery.draw()
} catch (e: NoSuchElementException) {
println("No more items to draw")
}
# Run all benchmarks (takes several hours)
cd WeightedLottery-benchmark
mvn exec:java -Dexec.mainClass="com.wl.benchmark.WeightedLotteryBenchmarkKt"
# Results saved to jmh-result.json
# Visualize at: https://jmh.morethan.io/
- π Wiki - Detailed documentation and examples
- π¬ Benchmark Details - Understanding performance tests
- π API Documentation - Complete API reference
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Add tests for your changes
- Run the test suite (
mvn test
) - Commit your changes (
git commit -am 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
If this library helped you, please consider giving it a star! β
- Author: Guy Kobrinsky
- LinkedIn: guykobrinsky
- Email: guy.kobrinsky@gmail.com
Built with β€οΈ for the JVM community