From 8ad8a38682c6402a8d23af3adc0f5bb2854a0e47 Mon Sep 17 00:00:00 2001 From: Ulisses Lima Date: Wed, 26 Oct 2022 03:44:35 -0300 Subject: [PATCH] BAEL-5678 - Creating Random Numbers With No Duplicates in Java (#12698) * BAEL-5678 - Creating Random Numbers With No Duplicates in Java Ready for review. * BAEL-5678 - review * using `isEmpty()` for `hasNext()`; * using `assertEquals` instead of `assertTrue`; --- .../com/baeldung/uniquerng/BigUniqueRng.java | 36 ++++++++++++ .../com/baeldung/uniquerng/UniqueRng.java | 42 ++++++++++++++ .../baeldung/uniquerng/RngUtilsUnitTest.java | 56 +++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/uniquerng/BigUniqueRng.java create mode 100644 core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/uniquerng/UniqueRng.java create mode 100644 core-java-modules/core-java-numbers-5/src/test/java/com/baeldung/uniquerng/RngUtilsUnitTest.java diff --git a/core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/uniquerng/BigUniqueRng.java b/core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/uniquerng/BigUniqueRng.java new file mode 100644 index 0000000000..468dce7b17 --- /dev/null +++ b/core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/uniquerng/BigUniqueRng.java @@ -0,0 +1,36 @@ +package com.baeldung.uniquerng; + +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.NoSuchElementException; +import java.util.Random; +import java.util.Set; + +public class BigUniqueRng implements Iterator { + + private Random random = new Random(); + private Set generated = new LinkedHashSet<>(); + + public BigUniqueRng(int size, int max) { + while (generated.size() < size) { + Integer next = random.nextInt(max); + generated.add(next); + } + } + + @Override + public Integer next() { + if (!hasNext()) + throw new NoSuchElementException(); + + Iterator iterator = generated.iterator(); + Integer next = iterator.next(); + iterator.remove(); + return next; + } + + @Override + public boolean hasNext() { + return !generated.isEmpty(); + } +} diff --git a/core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/uniquerng/UniqueRng.java b/core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/uniquerng/UniqueRng.java new file mode 100644 index 0000000000..01741562b3 --- /dev/null +++ b/core-java-modules/core-java-numbers-5/src/main/java/com/baeldung/uniquerng/UniqueRng.java @@ -0,0 +1,42 @@ +package com.baeldung.uniquerng; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +public class UniqueRng implements Iterator { + + private int size; + private List numbers = new ArrayList<>(); + + public UniqueRng(int size, boolean zeroBased) { + this.size = size; + int start = (zeroBased ? 0 : 1); + int limit = (zeroBased ? size - 1 : size); + + for (int i = start; i <= limit; i++) { + numbers.add(i); + } + + Collections.shuffle(numbers); + } + + @Override + public Integer next() { + if (!hasNext()) + throw new NoSuchElementException(); + + return numbers.remove(0); + } + + @Override + public boolean hasNext() { + return !numbers.isEmpty(); + } + + public int getSize() { + return size; + } +} diff --git a/core-java-modules/core-java-numbers-5/src/test/java/com/baeldung/uniquerng/RngUtilsUnitTest.java b/core-java-modules/core-java-numbers-5/src/test/java/com/baeldung/uniquerng/RngUtilsUnitTest.java new file mode 100644 index 0000000000..4680b53a78 --- /dev/null +++ b/core-java-modules/core-java-numbers-5/src/test/java/com/baeldung/uniquerng/RngUtilsUnitTest.java @@ -0,0 +1,56 @@ +package com.baeldung.uniquerng; + +import static org.junit.Assert.assertEquals; + +import java.util.Random; +import java.util.Set; +import java.util.TreeSet; +import java.util.stream.Collectors; + +import org.junit.Test; + +public class RngUtilsUnitTest { + + @Test + public void whenNUniqueNumRequested_thenNUniqueNumConsumed() { + TreeSet set = new TreeSet<>(); + int n = 5; + UniqueRng rng = new UniqueRng(n, true); + + while (rng.hasNext()) { + set.add(rng.next()); + } + + assertEquals(n, set.size()); + } + + @Test + public void givenYRange_whenNUniqueNumRequested_thenNUniqueNumConsumed() { + TreeSet set = new TreeSet<>(); + int n = 5; + int y = n * 10; + + BigUniqueRng rng = new BigUniqueRng(n, y); + while (rng.hasNext()) { + set.add(rng.next()); + } + + assertEquals(n, set.size()); + } + + @Test + public void givenIntStreamSizeN_whenCollected_thenSetSizeN() { + int n = 5; + int from = -5; + int to = n * 2; + + Random r = new Random(); + Set set = r.ints(from, to) + .distinct() + .limit(n) + .boxed() + .collect(Collectors.toSet()); + + assertEquals(n, set.size()); + } +}