diff --git a/primitiveCollections/src/main/java/org/lucares/collections/IntList.java b/primitiveCollections/src/main/java/org/lucares/collections/IntList.java index 3f54ae8..bd83560 100644 --- a/primitiveCollections/src/main/java/org/lucares/collections/IntList.java +++ b/primitiveCollections/src/main/java/org/lucares/collections/IntList.java @@ -3,7 +3,9 @@ package org.lucares.collections; import java.io.Serializable; import java.util.Arrays; import java.util.List; +import java.util.Random; import java.util.Spliterator.OfInt; +import java.util.concurrent.ThreadLocalRandom; import java.util.stream.IntStream; import java.util.stream.StreamSupport; @@ -483,6 +485,35 @@ public final class IntList implements Serializable, Cloneable { sorted = true; } + /** + * Shuffles the list. The permutation is uniformly distributed. + */ + public void shuffle() { + shuffle(ThreadLocalRandom.current()); + } + + /** + * Shuffles the list. The permutation is uniformly distributed. + * + * @param random + * the random number generator used + */ + public void shuffle(final Random random) { + + /* + * See Knuth, Donald E. Seminumerical algorithms. (1998). The Art of Computer + * Programming. 2. Addison–Wesley pp. 145–146. Algorithm P and exercise 18. + */ + for (int i = size() - 1; i > 0; i--) { + final int other = random.nextInt(i); + + final int tmp = data[other]; + data[other] = data[i]; + data[i] = tmp; + } + sorted = false; + } + private void ensureCapacity(final int newElements) { final int requiredCapacity = size + newElements; diff --git a/primitiveCollections/src/test/java/org/lucares/collections/IntListTest.java b/primitiveCollections/src/test/java/org/lucares/collections/IntListTest.java index ea8637a..3dc6ffa 100644 --- a/primitiveCollections/src/test/java/org/lucares/collections/IntListTest.java +++ b/primitiveCollections/src/test/java/org/lucares/collections/IntListTest.java @@ -7,6 +7,7 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.Arrays; import java.util.List; +import java.util.Random; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; @@ -488,8 +489,37 @@ public class IntListTest { list.addAll(4, 2, 3, 1); list.sort(); - final int[] expectedE = new int[] { 1, 2, 3, 4 }; - Assert.assertArrayEquals(expectedE, list.toArray()); + final int[] expected = new int[] { 1, 2, 3, 4 }; + Assert.assertArrayEquals(expected, list.toArray()); + } + + @Test + public void testSortParallel() { + final IntList list = new IntList(); + + list.addAll(4, 2, 3, 1); + list.parallelSort(); + + final int[] expected = new int[] { 1, 2, 3, 4 }; + Assert.assertArrayEquals(expected, list.toArray()); + } + + @Test + public void testShuffle() { + final IntList list = IntList.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); + final IntList original = list.clone(); + final IntList original2 = list.clone(); + + final Random random = new Random(1); + list.shuffle(random); + + Assert.assertEquals(original.size(), list.size()); + + original.removeAll(list); + Assert.assertTrue("original minus shuffled list: " + original, original.isEmpty()); + + list.removeAll(original2); + Assert.assertTrue("shuffled list minus original: " + list, list.isEmpty()); } private int[] removeElements(final int[] data, final int... removedIndices) {