├── .github
└── workflows
│ └── maven.yml
├── .gitignore
├── LICENSE
├── README.md
├── pom.xml
└── src
├── main
└── java
│ └── com
│ └── lewdev
│ └── probabilitylib
│ └── ProbabilityCollection.java
└── test
└── java
└── com
└── lewdev
└── probabilitylib
├── BenchmarkProbability.java
├── ExampleApp.java
├── ProbabilityCollectionTest.java
└── ProbabilityMap.java
/.github/workflows/maven.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a Java project with Maven
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
3 |
4 | name: Build
5 |
6 | on:
7 | push:
8 | branches: [ master ]
9 | pull_request:
10 | branches: [ master ]
11 |
12 | jobs:
13 | build:
14 |
15 | runs-on: ubuntu-latest
16 |
17 | steps:
18 | - uses: actions/checkout@v2
19 | - name: Set up JDK 1.8
20 | uses: actions/setup-java@v1
21 | with:
22 | java-version: 1.8
23 | - name: Build with Maven
24 | run: mvn -B package --file pom.xml
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | .classpath
3 | .project
4 | *.settings
5 | .editorconfig
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Lewys Davies
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Java-Probability-Collection
2 | [](https://scrutinizer-ci.com/g/lewysDavies/Java-Probability-Collection/?branch=master) [](https://scrutinizer-ci.com/g/lewysDavies/Java-Probability-Collection/build-status/master) [](https://jitpack.io/#lewysDavies/Java-Probability-Collection)
3 | Generic and Highly Optimised Java Data-Structure for Retrieving Random Elements with Probability
4 |
5 | # Usage
6 | ```
7 | ProbabilityCollection collection = new ProbabilityCollection<>();
8 | collection.add("A", 50); // 50 / 85 (total probability) = 0.588 * 100 = 58.8% Chance
9 | collection.add("B", 25); // 25 / 85 (total probability) = 0.294 * 100 = 29.4% Chance
10 | collection.add("C", 10); // 10 / 85 (total probability) = 0.117 * 100 = 11.7% Chance
11 |
12 | String random = collection.get();
13 | ```
14 |
15 | # Proven Probability
16 | The probability test is run **1,000,000 times**. Each time getting **100,000** random elements and counting the spread. The test would not pass if the spread had over **1%** deviation from the expected probability.
17 |
18 | A real world example is provided in ExampleApp.java (within the test folder), Typical Output with 100,000 gets::
19 | ```
20 | Prob | Actual
21 | -----------------------
22 | A: 58.824% | 58.975%
23 | B: 29.412% | 29.256%
24 | C: 11.765% | 11.769%
25 | ```
26 |
27 | # Performance
28 | Get performance has been significantly improved in comparison to my previous map implementation. This has been achieved with custom compared TreeSets.
29 | ```
30 | Benchmark Mode Cnt Score Error Units
31 | BenchmarkProbability.collectionAddSingle avgt 5 501.688 ± 33.925 ns/op
32 | BenchmarkProbability.collectionGet avgt 5 69.373 ± 2.198 ns/op
33 | BenchmarkProbability.mapAddSingle avgt 5 25809.712 ± 984.980 ns/op
34 | BenchmarkProbability.mapGet avgt 5 902.414 ± 22.388 ns/op
35 | ```
36 |
37 | # Installation
38 | **Super Simple: Copy ProbabilityCollection.java into your project**
39 | or for the fancy users, you could use Maven:
40 | **Repository:**
41 | ```
42 |
43 | jitpack.io
44 | https://jitpack.io
45 |
46 | ```
47 | **Dependency:**
48 | ```
49 |
50 | com.github.lewysDavies
51 | Java-Probability-Collection
52 | v0.8
53 |
54 | ```
55 | **Maven Shade This Dependency:**
56 | ```
57 |
58 | org.apache.maven.plugins
59 | maven-shade-plugin
60 | 3.1.1
61 |
62 |
63 |
64 |
65 |
66 |
67 | com.lewdev.probabilitylib
68 | ******.probabilitylib
69 |
70 |
71 |
72 | package
73 |
74 | shade
75 |
76 |
77 |
78 |
79 | ```
80 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
4 | 4.0.0
5 |
6 | com.lewdev
7 | probability-lib
8 | 0.8
9 | jar
10 |
11 | probability-lib
12 | lewdev.uk
13 |
14 |
15 | UTF-8
16 | 1.8
17 | 1.23
18 |
19 |
20 |
21 |
22 | org.junit.jupiter
23 | junit-jupiter-engine
24 | 5.1.0
25 | test
26 |
27 |
28 |
29 | org.hamcrest
30 | hamcrest-core
31 | 1.3
32 | test
33 |
34 |
35 |
36 | org.openjdk.jmh
37 | jmh-core
38 | ${jmh.version}
39 |
40 |
41 | org.openjdk.jmh
42 | jmh-generator-annprocess
43 | ${jmh.version}
44 |
45 |
46 |
47 |
48 |
49 |
50 | org.apache.maven.plugins
51 | maven-compiler-plugin
52 | 3.1
53 |
54 | ${java.version}
55 | ${java.version}
56 |
57 |
58 |
59 |
60 | org.apache.maven.plugins
61 | maven-shade-plugin
62 | 3.2.0
63 |
64 |
65 | package
66 |
67 | shade
68 |
69 |
70 | benchmarks
71 |
72 |
74 | org.openjdk.jmh.Main
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/src/main/java/com/lewdev/probabilitylib/ProbabilityCollection.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2020 Lewys Davies
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in all
12 | * copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | */
22 | package com.lewdev.probabilitylib;
23 |
24 | import java.util.Comparator;
25 | import java.util.Iterator;
26 | import java.util.NavigableSet;
27 | import java.util.Objects;
28 | import java.util.SplittableRandom;
29 | import java.util.TreeSet;
30 |
31 | /**
32 | * ProbabilityCollection for retrieving random elements based on probability.
33 | *
34 | *
35 | * Selection Algorithm Implementation:
36 | *
37 | *
38 | *
Elements have a "block" of space, sized based on their probability share
39 | *
"Blocks" start from index 1 and end at the total probability of all
40 | * elements
41 | *
A random number is selected between 1 and the total probability
42 | *
Which "block" the random number falls in is the element that is selected
43 | *
Therefore "block"s with larger probability have a greater chance of being
44 | * selected than those with smaller probability.
45 | *