Class RandomStreams


  • public final class RandomStreams
    extends java.lang.Object
    Utility for creating streams using a source of randomness.
    Since:
    1.5
    • Nested Class Summary

      Nested Classes 
      Modifier and Type Class Description
      static interface  RandomStreams.SeededObjectFactory<T>
      A factory for creating objects using a seed and a using a source of randomness.
      private static class  RandomStreams.SeededObjectSpliterator<T>
      Spliterator for streams of a given object type that can be created from a seed and source of randomness.
    • Field Summary

      Fields 
      Modifier and Type Field Description
      private static int SEED_CHAR_BITS
      The number of bits of each random character in the seed.
    • Constructor Summary

      Constructors 
      Modifier Constructor Description
      private RandomStreams()
      Class contains only static methods.
    • Field Detail

      • SEED_CHAR_BITS

        private static final int SEED_CHAR_BITS
        The number of bits of each random character in the seed. The generation algorithm will work if this is in the range [2, 30].
        See Also:
        Constant Field Values
    • Constructor Detail

      • RandomStreams

        private RandomStreams()
        Class contains only static methods.
    • Method Detail

      • generateWithSeed

        public static <T> java.util.stream.Stream<T> generateWithSeed​(long streamSize,
                                                                      SplittableUniformRandomProvider source,
                                                                      RandomStreams.SeededObjectFactory<T> factory)
        Returns a stream producing the given streamSize number of new objects generated using the supplied source of randomness and object factory.

        A long seed is provided for each object instance using the stream position and random bits created from the supplied source.

        The stream supports parallel execution by splitting the provided source of randomness. Consequently objects in the same position in the stream created from a sequential stream may be created from a different source of randomness than a parallel stream; it is not expected that parallel execution will create the same final collection of objects.

        Type Parameters:
        T - the object type
        Parameters:
        streamSize - Number of objects to generate.
        source - A source of randomness used to initialise the new instances; this may be split to provide a source of randomness across a parallel stream.
        factory - Factory to create new instances.
        Returns:
        a stream of objects; the stream is limited to the given streamSize.
        Throws:
        java.lang.IllegalArgumentException - if streamSize is negative.
        java.lang.NullPointerException - if source or factory is null.
      • createSeed

        static long createSeed​(UniformRandomProvider rng)
        Creates a seed to prepend to a counter. The seed is created to satisfy the following requirements:
        • The least significant bit is set
        • The seed is composed of characters from an n-bit alphabet
        • The character used in the least significant bits is unique
        • The other characters are sampled uniformly from the remaining (n-1) characters

        The composed seed is created using ((seed << shift) | count) where the shift is applied to ensure non-overlap of the shifted seed and the count. This is achieved by ensuring the lowest 1-bit of the seed is above the highest 1-bit of the count. The shift is a multiple of n to ensure the character used in the least significant bits aligns with higher characters after a shift. As higher characters exclude the least significant character no shifted seed can duplicate previously observed composed seeds. This holds until the least significant character itself is shifted out of the composed seed.

        The seed generation algorithm starts with a random series of bits with the lowest bit set. Any occurrences of the least significant character in the remaining characters are replaced using UniformRandomProvider.nextInt().

        The remaining characters will be rejected at a rate of 2-n. The character size is a compromise between a low rejection rate and the highest supported count that may receive a prepended seed.

        The JDK's java.util.random package uses 4-bits for the character size when creating a stream of SplittableGenerator. This achieves a rejection rate of 1/16. Using this size will require 1 call to generate a long and on average 1 call to nextInt(15). The maximum supported stream size with a unique seed per object is 260. The algorithm here also uses a character size of 4-bits; this simplifies the implementation as there are exactly 16 characters. The algorithm is a different implementation to the JDK and creates an output seed with similar properties.

        Parameters:
        rng - Source of randomness.
        Returns:
        the seed