tl;dr
In Java syntax:
List < String > range =
IntStream
.range ( 10_000_000 , 20_000_000 ) // Generate a sequence of all desired values, rather than generate random numbers.
.mapToObj ( ( int i ) -> "83" + i ) // Convert from `int` primitive to `String` object, and prepend "83".
.collect ( Collectors.toCollection ( ArrayList :: new ) );
Collections.shuffle ( range , random );
Files.write ( Paths.get ( "/tmp/numbers.txt" ) , range );
Executes in 2-3 seconds on a laptop computer.
Or we can try this nifty nearly-one-liner based on Comment by Johannes Kuhn. But this takes longer, upwards of twice as long at 3.5 to 4.5 seconds.
try
{
Files.write (
Paths.get ( "/tmp/numbers.txt" ) ,
SecureRandom
.getInstance( "NativePRNG" )
.ints ( 0 , 20_000_000 )
.distinct ( )
.limit ( 10_000_000 )
.mapToObj ( ( int i ) -> "83" + i )
.toList ( )
);
}
catch ( IOException e ) { throw new RuntimeException ( e ); }
Generate a sequence of numbers, not random numbers
Apparently you want ten million numbers between ten million and twenty million. Notice that means simply the range from 10,000,000 and 20,000,000. Your range of possible values equates to your range of desired results. So we can start by assembling a sequence of ten-twenty million.
We use IntStream.range
to assemble the sequence of numbers as a stream of int
values.
You said you want to treat each number as text, and prepend the text "83"
. So we use Stream::map
to convert each number to text along with the prepend.
I do not yet know Groovy, so I'll use Java syntax.
List < String > range =
IntStream
.range ( 10_000_000 , 20_000_000 )
.mapToObj ( ( int i ) -> "83" + i )
.collect ( Collectors.toCollection ( ArrayList :: new ) );
Report first and last values to verify.
System.out.println ( range.get ( 0 ) + " - " + range.get ( range.size ( ) - 1 ) );
And you want this sequence of ten million strings in random order. So call Collections.shuffle
to re-order them randomly. No need to generate random numbers.
Collections.shuffle ( range );
Report first and last values to verify.
System.out.println ( range.get ( 0 ) + " - " + range.get ( range.size ( ) - 1 ) );
When run:
8310000000 - 8319999999
8315634260 - 8311372639
Strong random number generator
If you need a more cryptographically strong random number generator than provided by default to perform the shuffle, you can pass an alternate source of randomness. This can be Random
or any subclass, including SecureRandom
. For example:
Collections.shuffle (
range ,
SecureRandom.getInstance( "DRBG" )
);
I am no expert on random number generators. But I am guessing these may be of interest to you:
I gather from those documents that via the Java Service provider interface and SecureRandomSpi
class, you can plug in third-party generator implementations in addition to the new-and-improved ones bundled with some JDKs.
Write file
And you said you need to write these to a file. The List
of strings is itself an Iterable
. So we can merely pass to Files.write
, a method in the Java NIO package of modern file-handling classes.
try
{
Files.write (
Paths.get ( "/tmp/numbers.txt" ) ,
range
);
}
catch ( IOException e ) { throw new RuntimeException ( e ); }
}
The resulting file is 110 MB in size.
Performance
You will need a bit of free memory to run the code above. We create all the data in memory before writing to storage. I would guess it takes about 200 to 300 MB of RAM, given the file size reported above.
You have a concern about speed of execution. So let's run it once, then run several times to get an average of elapsed time. For more serious benchmarking, use JMH.
app.randomWrite ( );
int repetitions = 10;
List < Duration > durations = new ArrayList <> ( repetitions );
for ( int index = 0 ; index < repetitions ; index++ ) durations.add ( app.randomWrite ( ) );
System.out.println ( "durations = " + durations );
When run on an Apple MacBook Pro with Apple M1 Pro chip, 16 GB memory, and internal solid-state storage, the execution times are around 2.5 seconds, in a range of 2-3 seconds.
durations = [PT2.501965458S, PT2.315898625S, PT2.398674875S, PT2.24017325S, PT2.047942S]