0

I want to create a unique number of "Long" type using java. I have seen few examples but they were using timestamp, without using timestamp can i create a unique number of wrapper object "Long" .Please suggest.

please suggest.Thanks.

user3684675
  • 381
  • 4
  • 8
  • 32
  • 1
    What are your requirements? Distributed computing, durability, etc? Simplest would just be an `AtomicLong`, or even just a plain `long` if you don't need it to be safe for multi threading. – yshavit Jul 02 '14 at 12:48

7 Answers7

1

Generate each digit by calling random.nextInt. For uniqueness, you can keep track of the random numbers you have used so far by keeping them in a set and checking if the set contains the number you generate each time.

public static long generateRandom(int length) {
    Random random = new Random();
    char[] digits = new char[length];
    digits[0] = (char) (random.nextInt(9) + '1');
    for (int i = 1; i < length; i++) {
        digits[i] = (char) (random.nextInt(10) + '0');
    }
    return Long.parseLong(new String(digits));
}
MRebai
  • 5,344
  • 3
  • 33
  • 52
  • 1
    That's going to be pretty slow and memory-intensive compared to other possible answers, especially depending on how many ids are needed. – yshavit Jul 02 '14 at 12:51
  • i just give him an answer he could choose what he need – MRebai Jul 02 '14 at 12:52
  • The answer you provided assumes OP doesn't have distributed computing or durability concerns (or else just keeping a Set won't be enough). For that, a simple `AtomicLong` would be just as effective, and much simpler and more efficient. – yshavit Jul 02 '14 at 12:54
  • I posted a comment, since the OP has not posted enough information in the question for us to provide a really solid answer. – yshavit Jul 02 '14 at 12:56
1

Without using timestamp, you have these options:

  1. Keep a record of all previously generated numbers -- of course you have to store them somewhere, which is unwieldy
  2. Store the previous number, and increment each time.
  3. Simply assume that the PRNG will never come up with the same number twice. Since there are 2^64 == 1.8 * 10^19 possible values, this is a very safe bet.
slim
  • 40,215
  • 13
  • 94
  • 127
1

Many of the answers suggest using Math.random() to generate the unique id. Now Math.random() is actually not random at all, and does in itself not add anything unique. The seemingly uniqueness comes from the default seeding in the Math.random() based on System.currentTimeMillis(); with the following code:

/**
 * Construct a random generator with the current time of day in milliseconds
 * as the initial state.
 * 
 * @see #setSeed
 */
public Random() {
    setSeed(System.currentTimeMillis() + hashCode());
}

So why not just remove the Math.Random() from the equation and just use System.currentTimeMillis() in the counter.

Time based unique numbers:

The following code implements a unique number generator based solemnly on time. The benefit of this is that you don't need to store any counters etc. The numbers generated will be unique under the following condition: The code only runs in one JVM at any time periode - this is important, as the timestamp is part of the key.

public class UniqueNumber {
    private static UniqueNumber instance = null;  
    private long currentCounter;

    private UniqueNumber() {
        currentCounter = (System.currentTimeMillis() + 1) << 20; 
    }

    private static synchronized UniqueNumber getInstance() {
        if (instance == null) {
            instance = new UniqueNumber(); 
        }
        return instance;
    }

    private synchronized long nextNumber() {
        currentCounter++;
        while (currentCounter > (System.currentTimeMillis() << 20)) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
            }
        }
        return currentCounter;
    }

    static long getUniqueNumber() {
        return getInstance().nextNumber();
    }
}

The code allows for up to 2^20 numbers to be generated per millisecond (provided you have access to that fast hardware). If this rate is exceeded the code will sleep until next tick of System.currentTimeMillis()

Testing the code:

public static void main(String[] args) {
    for (int i = 0; i < 10; i++) {
        System.out.println(UniqueNumber.getUniqueNumber());
    }
}

Output:

1472534126716256257
1472534126716256258
1472534126716256259
1472534126716256260
1472534126716256261
1472534126716256262
1472534126716256263
1472534126716256264
1472534126716256265
1472534126716256266
Ebbe M. Pedersen
  • 7,250
  • 3
  • 27
  • 47
  • Would it be better to append timestamp with random like this: Long.parse(System.currentTimeMillis() + +""+ Math.round(Math.random()*100)); – donlys Dec 18 '16 at 16:54
  • @donlys Try generating more than 100 id's in a tight loop, and you will see that that approach don't generate unique id's .. – Ebbe M. Pedersen Dec 18 '16 at 20:25
  • Ok. Can you explain what << 20 does - I understand that it shifts 20 bits to the left - but what does that translate to as a number? Is there specific reason for 20? Also will that leave 20 bits on the right as 0s - which I can use to add random numbers or will that result in number bigger than long in future? – donlys Dec 19 '16 at 15:32
  • @donlys The implementation uses currentTimeMillis() to initialize a counter. As currentTimeMillis() (currently) only uses the 41 first bits, the algorithm just makes use of some of the rest of the 64 bits of the long by shifting the counter 20 bits. Without the switch, the implementation will only allow 1 id per millisecond, with the shift, the counter will allow up to 2^20 id's per millisec. What are you trying to solve by adding random numbers ? It won't be more unique this way .. – Ebbe M. Pedersen Dec 19 '16 at 16:21
  • I want sequential UID created from Java instead of relying on db seq.nextval. So I think I can use your technique. I am though now wondering if I should use long or uuid stored in char(16) binary as that performs equally well? – donlys Dec 20 '16 at 00:10
  • Another question: being a singleton currentCounter is initialized to System.currentTimeMillis() only once. So will it create duplicates if I create let's say 2^20 in 1 millisecond, then restart my JVM and then create 2^20 again? – donlys Dec 21 '16 at 13:58
  • @donlys The code ensures that it only makes counters in the range from the first call to currentTimeMillis() and the current time .. If capacity is exceeded it do a Thread.sleep(1); – Ebbe M. Pedersen Dec 21 '16 at 15:27
0

Take a look on this Commons Id, it has LongGenerator that generates an incrementing number as a Long object.

Aleksandr Podkutin
  • 2,532
  • 1
  • 20
  • 31
  • Thanks for all the answers, requirement is simple, i want to pass object of Long type and should be unique. – user3684675 Jul 02 '14 at 12:54
  • @user3684675 So "Commons Id" it's all you need, it's give you an unique Long objects. – Aleksandr Podkutin Jul 02 '14 at 12:58
  • "Unique" is ambiguous. Unique across _what_? A single instance of the JVM? Multiple instances at the same time? Multiple instances, but run in one at a time? – yshavit Jul 02 '14 at 13:38
  • @yshavit , i'm saving this Long unique number in the database, so it should be unique and whatever number it generated before should not generate as it violates primary key constraint applied to that field in the database. – user3684675 Jul 02 '14 at 14:08
  • In that case, what about just using the database's auto increment feature to generate the id for you? That's the most robust option. – yshavit Jul 02 '14 at 14:14
0

This will create simply a random long number -

System.out.println((long)((Math.random())*1000000000000000000L));
Ninad Pingale
  • 6,801
  • 5
  • 32
  • 55
0

You can generate random numbers using java.util.Random and add them to a java.util.Set this will ensure that no duplicate is allowed

SparkOn
  • 8,806
  • 4
  • 29
  • 34
0

Try with UUID as:

  Long uniqueLong = UUID.randomUUID().getMostSignificantBits();

Here, you find a very good explanation as to why this could be unique in terms of randomness.

Community
  • 1
  • 1
Prasad
  • 3,785
  • 2
  • 14
  • 23