From bbc22e6924cfd6a7b46b5e9ddc8d502e530111be Mon Sep 17 00:00:00 2001
From: PiggyPiglet
Date: Sat, 18 Jul 2020 00:33:40 +0800
Subject: [PATCH 1/2] Added ij to gitignore
---
.gitignore | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/.gitignore b/.gitignore
index 00fe968..d11dd98 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
-/target/
+target/
.classpath
.project
*.settings
-.editorconfig
\ No newline at end of file
+.editorconfig
+.idea/
+*.iml
\ No newline at end of file
From d7bb2f35f6175e0f2bbbedf9e821cba932bc29ca Mon Sep 17 00:00:00 2001
From: PiggyPiglet
Date: Sat, 18 Jul 2020 00:48:04 +0800
Subject: [PATCH 2/2] Use annotations instead of null checks Remove redundant
method modifiers Use final where appropriate Fix bad javadocs
---
pom.xml | 9 +
.../probabilitylib/ProbabilityCollection.java | 423 ++++++++----------
.../ProbabilityCollectionTest.java | 29 +-
3 files changed, 211 insertions(+), 250 deletions(-)
diff --git a/pom.xml b/pom.xml
index f1fe868..08f03ef 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,6 +18,15 @@
+
+ org.jetbrains
+ annotations
+ 19.0.0
+ compile
+
+
+
org.junit.jupiter
junit-jupiter-engine
diff --git a/src/main/java/com/lewdev/probabilitylib/ProbabilityCollection.java b/src/main/java/com/lewdev/probabilitylib/ProbabilityCollection.java
index 98bd9b1..0faa8f9 100644
--- a/src/main/java/com/lewdev/probabilitylib/ProbabilityCollection.java
+++ b/src/main/java/com/lewdev/probabilitylib/ProbabilityCollection.java
@@ -1,32 +1,30 @@
/*
-* Copyright (c) 2020 Lewys Davies
-*
-* Permission is hereby granted, free of charge, to any person obtaining a copy
-* of this software and associated documentation files (the "Software"), to deal
-* in the Software without restriction, including without limitation the rights
-* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-* copies of the Software, and to permit persons to whom the Software is
-* furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included in all
-* copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-* SOFTWARE.
-*/
+ * Copyright (c) 2020 Lewys Davies
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
package com.lewdev.probabilitylib;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.NavigableSet;
-import java.util.Objects;
-import java.util.SplittableRandom;
-import java.util.TreeSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
/**
* ProbabilityCollection for retrieving random elements based on probability.
@@ -43,214 +41,187 @@
* selected than those with smaller probability.
*
*
- *
- * @author Lewys Davies
- * @version 0.8
*
* @param Type of elements
+ * @author Lewys Davies
+ * @version 0.8
*/
public class ProbabilityCollection {
-
- private final NavigableSet> collection;
- private final SplittableRandom random = new SplittableRandom();
+ private final NavigableSet> collection =
+ new TreeSet<>(Comparator.comparingInt(ProbabilitySetElement::getIndex));
+ private final SplittableRandom random = new SplittableRandom();
+
+ private int totalProbability = 0;
+
+ /**
+ * @return Number of objects inside the collection
+ */
+ public int size() {
+ return this.collection.size();
+ }
+
+ /**
+ * @return True if collection contains no elements, else False
+ */
+ public boolean isEmpty() {
+ return this.collection.isEmpty();
+ }
+
+ /**
+ * @param object Object to test against
+ * @return True if collection contains the object, else False
+ * @throws IllegalArgumentException if object is null
+ */
+ public boolean contains(@NotNull E object) {
+ return this.collection.stream()
+ .anyMatch(entry -> entry.getObject().equals(object));
+ }
+
+ /**
+ * @return Iterator over this collection
+ */
+ @NotNull
+ public Iterator> iterator() {
+ return this.collection.iterator();
+ }
+
+ /**
+ * Add an object to this collection
+ *
+ * @param object Non-null object to add.
+ * @param probability share. Must be greater than 0.
+ * @throws IllegalArgumentException if probability <= 0
+ */
+ public void add(@NotNull E object, int probability) {
+ if (probability <= 0) {
+ throw new IllegalArgumentException("Probability must be greater than 0");
+ }
+
+ final ProbabilitySetElement entry = new ProbabilitySetElement<>(object, probability);
+ entry.setIndex(this.totalProbability + 1);
+
+ this.collection.add(entry);
+ this.totalProbability += probability;
+ }
+
+ /**
+ * Remove a object from this collection
+ *
+ * @param object Object to remove
+ * @return True if object was removed, else False.
+ */
+ public boolean remove(@NotNull E object) {
+ final Iterator> it = this.iterator();
+ boolean removed = false;
+
+ while (it.hasNext()) {
+ ProbabilitySetElement entry = it.next();
+
+ if (entry.getObject().equals(object)) {
+ this.totalProbability -= entry.getProbability();
+ it.remove();
+ removed = true;
+ }
+ }
+
+ this.updateIndexes();
+
+ return removed;
+ }
+
+ /**
+ * Remove all objects from this collection
+ */
+ public void clear() {
+ this.collection.clear();
+ this.totalProbability = 0;
+ }
+
+ /**
+ * Get a random object from this collection, based on probability.
+ *
+ * @return Random object
+ * @throws IllegalStateException if this collection is empty
+ */
+ @NotNull
+ public E get() {
+ if (this.isEmpty()) {
+ throw new IllegalStateException("Cannot get an object out of a empty collection");
+ }
+
+ final ProbabilitySetElement toFind = new ProbabilitySetElement<>(null, 0);
+ toFind.setIndex(this.random.nextInt(1, this.totalProbability + 1));
+
+ return Objects.requireNonNull(Objects.requireNonNull(this.collection.floor(toFind)).getObject());
+ }
+
+ /**
+ * @return Sum of all element's probability
+ */
+ public final int getTotalProbability() {
+ return this.totalProbability;
+ }
+
+ /*
+ * Calculate the size of all element's "block" of space:
+ * i.e 1-5, 6-10, 11-14, 15, 16
+ *
+ * We then only need to store the start index of each element,
+ * as we make use of the TreeSet#floor
+ */
+ private void updateIndexes() {
+ int previousIndex = 0;
+
+ for (final ProbabilitySetElement entry : this.collection) {
+ previousIndex = entry.setIndex(previousIndex + 1) + (entry.getProbability() - 1);
+ }
+ }
- private int totalProbability;
-
- /**
- * Construct a new Probability Collection
- */
- public ProbabilityCollection() {
- this.collection = new TreeSet<>(Comparator.comparingInt(ProbabilitySetElement::getIndex));
- this.totalProbability = 0;
- }
+ /**
+ * Used internally to store information about a object's
+ * state in a collection. Specifically, the probability
+ * and index within the collection.
+ *
+ * Indexes refer to the start position of this element's "block" of space.
+ * The space between element "block"s represents their probability of being selected
+ *
+ * @param Type of element
+ * @author Lewys Davies
+ */
+ private static final class ProbabilitySetElement {
+ private final T object;
+ private final int probability;
+ private int index;
- /**
- * @return Number of objects inside the collection
- */
- public int size() {
- return this.collection.size();
- }
-
- /**
- * @return True if collection contains no elements, else False
- */
- public boolean isEmpty() {
- return this.collection.isEmpty();
- }
-
- /**
- * @param object
- * @return True if collection contains the object, else False
- * @throws IllegalArgumentException if object is null
- */
- public boolean contains(E object) {
- if(object == null) {
- throw new IllegalArgumentException("Cannot check if null object is contained in this collection");
- }
-
- return this.collection.stream()
- .anyMatch(entry -> entry.getObject().equals(object));
- }
+ protected ProbabilitySetElement(T object, int probability) {
+ this.object = object;
+ this.probability = probability;
+ }
- /**
- * @return Iterator over this collection
- */
- public Iterator> iterator() {
- return this.collection.iterator();
- }
-
- /**
- * Add an object to this collection
- *
- * @param object. Not null.
- * @param probability share. Must be greater than 0.
- *
- * @throws IllegalArgumentException if object is null
- * @throws IllegalArgumentException if probability <= 0
- */
- public void add(E object, int probability) {
- if(object == null) {
- throw new IllegalArgumentException("Cannot add null object");
- }
-
- if(probability <= 0) {
- throw new IllegalArgumentException("Probability must be greater than 0");
- }
-
- ProbabilitySetElement entry = new ProbabilitySetElement(object, probability);
- entry.setIndex(this.totalProbability + 1);
-
- this.collection.add(entry);
- this.totalProbability += probability;
- }
+ /**
+ * @return The actual object
+ */
+ @Nullable
+ public T getObject() {
+ return this.object;
+ }
- /**
- * Remove a object from this collection
- *
- * @param object
- * @return True if object was removed, else False.
- *
- * @throws IllegalArgumentException if object is null
- */
- public boolean remove(E object) {
- if(object == null) {
- throw new IllegalArgumentException("Cannot remove null object");
- }
-
- Iterator> it = this.iterator();
- boolean removed = false;
-
- while(it.hasNext()) {
- ProbabilitySetElement entry = it.next();
- if(entry.getObject().equals(object)) {
- this.totalProbability -= entry.getProbability();
- it.remove();
- removed = true;
- }
- }
-
- this.updateIndexes();
-
- return removed;
- }
-
- /**
- * Remove all objects from this collection
- */
- public void clear() {
- this.collection.clear();
- this.totalProbability = 0;
- }
-
- /**
- * Get a random object from this collection, based on probability.
- *
- * @return Random object
- *
- * @throws IllegalStateException if this collection is empty
- */
- public E get() {
- if(this.isEmpty()) {
- throw new IllegalStateException("Cannot get an object out of a empty collection");
- }
-
- ProbabilitySetElement toFind = new ProbabilitySetElement<>(null, 0);
- toFind.setIndex(this.random.nextInt(1, this.totalProbability + 1));
-
- return Objects.requireNonNull(this.collection.floor(toFind).getObject());
- }
-
- /**
- * @return Sum of all element's probability
- */
- public final int getTotalProbability() {
- return this.totalProbability;
- }
-
- /*
- * Calculate the size of all element's "block" of space:
- * i.e 1-5, 6-10, 11-14, 15, 16
- *
- * We then only need to store the start index of each element,
- * as we make use of the TreeSet#floor
- */
- private final void updateIndexes() {
- int previousIndex = 0;
-
- for(ProbabilitySetElement entry : this.collection) {
- previousIndex = entry.setIndex(previousIndex + 1) + (entry.getProbability() - 1);
- }
- }
-
- /**
- * Used internally to store information about a object's
- * state in a collection. Specifically, the probability
- * and index within the collection.
- *
- * Indexes refer to the start position of this element's "block" of space.
- * The space between element "block"s represents their probability of being selected
- *
- * @author Lewys Davies
- *
- * @param Type of element
- */
- final static class ProbabilitySetElement {
- private final T object;
- private final int probability;
- private int index;
-
- /**
- * @param object
- * @param probability
- */
- protected ProbabilitySetElement(T object, int probability) {
- this.object = object;
- this.probability = probability;
- }
+ /**
+ * @return Probability share in this collection
+ */
+ public int getProbability() {
+ return this.probability;
+ }
- /**
- * @return The actual object
- */
- public final T getObject() {
- return this.object;
- }
+ // Used internally, see this class's documentation
+ private int getIndex() {
+ return this.index;
+ }
- /**
- * @return Probability share in this collection
- */
- public final int getProbability() {
- return this.probability;
- }
-
- // Used internally, see this class's documentation
- private final int getIndex() {
- return this.index;
- }
-
- // Used Internally, see this class's documentation
- private final int setIndex(int index) {
- this.index = index;
- return this.index;
- }
- }
+ // Used Internally, see this class's documentation
+ private int setIndex(int index) {
+ this.index = index;
+ return this.index;
+ }
+ }
}
diff --git a/src/test/java/com/lewdev/probabilitylib/ProbabilityCollectionTest.java b/src/test/java/com/lewdev/probabilitylib/ProbabilityCollectionTest.java
index 5bd0aae..277aeb4 100644
--- a/src/test/java/com/lewdev/probabilitylib/ProbabilityCollectionTest.java
+++ b/src/test/java/com/lewdev/probabilitylib/ProbabilityCollectionTest.java
@@ -1,10 +1,10 @@
package com.lewdev.probabilitylib;
-import static org.junit.jupiter.api.Assertions.*;
-
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+
/**
* @author Lewys Davies
*/
@@ -250,48 +250,29 @@ public void test_Errors() {
assertEquals(0, collection.size());
assertTrue(collection.isEmpty());
assertEquals(0, collection.getTotalProbability());
-
+
// Cannot get from empty collection
- assertThrows(IllegalStateException.class, () -> {
- collection.get();
- });
+ assertThrows(IllegalStateException.class, collection::get);
assertEquals(0, collection.size());
assertTrue(collection.isEmpty());
assertEquals(0, collection.getTotalProbability());
- // Cannot add null object
- assertThrows(IllegalArgumentException.class, () -> {
- collection.add(null, 1);
- });
-
assertEquals(0, collection.size());
assertTrue(collection.isEmpty());
assertEquals(0, collection.getTotalProbability());
// Cannot add prob 0
- assertThrows(IllegalArgumentException.class, () -> {
- collection.add("A", 0);
- });
+ assertThrows(IllegalArgumentException.class, () -> collection.add("A", 0));
assertEquals(0, collection.size());
assertTrue(collection.isEmpty());
assertEquals(0, collection.getTotalProbability());
- // Cannot remove null
- assertThrows(IllegalArgumentException.class, () -> {
- collection.remove(null);
- });
-
assertEquals(0, collection.size());
assertTrue(collection.isEmpty());
assertEquals(0, collection.getTotalProbability());
- // Cannot contains null
- assertThrows(IllegalArgumentException.class, () -> {
- collection.contains(null);
- });
-
assertEquals(0, collection.size());
assertTrue(collection.isEmpty());
assertEquals(0, collection.getTotalProbability());