0

I am using Apache Commons Lang3 package class RandomStringUtils. After generating some numbers, RandomStringUtils.randomNumeric is generating duplicate numbers in an infinite loop. How can I prevent this from happening?

Here is my code:

quantity = 100000
insertedNum = 0;
length = 9;
String[] numGen = new String[100];
idx = 1;

while (insertedNum < quantity) {
    String random=RandomStringUtils.randomNumeric(length);
    numGen[idx - 1] = random;
    if (idx == 100) {
        insertedNum += DB Code. If unique constraint error then discard batch return 0 else execute batch return inserted count.
        idx = 1;
        numGen = new String[100];
    }
    else
        idx++;
    }
}
  • I am surprised to see why you won';t have an ArrayIndexOutOfBoundsException in the very first run of your loop where, **numGen[idx - 1] = random** , since **idx = 0** just before the while loop?? – ShayHaned Jul 05 '17 at 07:37
  • Hi @ShayHaned. I have updated – Manisha Singh Jul 05 '17 at 10:55

2 Answers2

0

Firstly you have a bug numGen[idx - 1] = random;

When first entering the loop the idx is 0 so you are assigning to -1 field in numGen. 2ndly it will not continue forever, but if it does for a long time you can take different approach when generating strings, instead of deleting whole batch, regenerate them one by one if they exist in the current batch.

Try checking after each generation if the number has not yet been generated in this batch. You can use java map or set to mark all seen numbers in the batch for lookup to be faster.

So add code for your solution to look something along those lines:

quantity = 100000
insertedNum = 0;
length = 9;
String[] numGen = new String[100];
idx = 0;
Set<string> seenThisBatch = new HashSet<string>();
while (insertedNum < quantity) {
            String random=RandomStringUtils.randomNumeric(length);
            //in case of duplicates, keep on generating
            while(seenThisBatch.contains(random){
                  random=RandomStringUtils.randomNumeric(length);
            }
            //add it to set
            seenThisBatch.add(random);
            numGen[idx - 1] = random;
            if (idx == 100) {
                //clear the batch set
                seenThisBatch.clear();
                insertedNum += DB Code. If unique constraint error then discard batch return 0 else execute batch return inserted count.
                idx = 1;
                numGen = new String[100];
            }
            else
              idx++;
        }
cerkiewny
  • 2,761
  • 18
  • 36
  • I try to generate them one by one, but after one point again duplicate numbers are generating – Manisha Singh Jul 05 '17 at 11:02
  • @ManishaSingh are they meant to be all unique? or are they mean to be unique on the batch basis if they all need to be unique than just remove .clear and all should work – cerkiewny Jul 05 '17 at 11:49
0

A cumbersome approach would be to keep regenerating random strings till you find that you have encountered a unique random string that is not already contained in your array. All you have to do is check whether the newly generated random string is already in the array or not

quantity = 100000
insertedNum = 0;
length = 9;
String[] numGen = new String[100];
idx = 0;
String random = "";
while (insertedNum < quantity) {
            random=RandomStringUtils.randomNumeric(length);
            while( isAlreadyInArray( numGen , random ) )
            {
                //regenerate a random string
                random = RandomStringUtils.randomNumeric( length );
            }
            // Add it to your array, and increment it by one
            numGen[idx] = random;
            idx = (idx + 1) % numGen.length;
            // In this case, the array got populated to completion
            if (idx == 0) {
                System.out.println( java.util.Arrays.toString( numGen ) );  
                //clear the batch set
                insertedNum += DB Code. If unique constraint error then discard batch return 0 else execute batch return inserted count.
                numGen = new String[100];
            }
        }

And here is the helper method isAlreadyInArray( String[] array , String someVal )

public boolean isAlreadyInArray( String[] mData , String strToCheck )
{
    for( int x = 0; x < mData.length; x++ )
    {
        if( mData[x] != null && mData[x].equalsIgnoreCase( strToCheck ) )
        {
            return true;    
        }
    }
    return false;
}

Please run this sample, and if it fails to help, then certainly we can re-iterate over the problem :)

ShayHaned
  • 358
  • 3
  • 8
  • Question was RandomStringUtils is generating duplicate numbers. If you are taking array, still that array will may have duplicate numbers so loop may go infinite. I need clear approach if I can avoid duplicate generation – Manisha Singh Jul 05 '17 at 11:00
  • Are you still getting duplicate **Strings** in the array after running the above code?? It's really impossible though. Please run the code atleast, present a sample array in the comment after running the code?? And I thought we were generating random **Strings** instead of **int** here?? – ShayHaned Jul 05 '17 at 13:25
  • **public static String randomNumeric(int count)** Does NOT generate random numbers. It generates random Strings. Please make sure what you are asking here?? Please run the code and present a sample that seems inappropriate – ShayHaned Jul 05 '17 at 13:27