android app, it needs to generate a random int key for different use cases. it has a function for the random int, which is fine in most time, but in the case if it is called frequently it may return a same number.
int nextRandomId() {
return (int) SystemClock.uptimeMillis();
}
one of the case when build the notification action buttons, there will be multiple action button
each will have its own pendingIntent with requestid from nextRandomId().
Intent broadcastIntent_one = Intent(this, NotificationReceiver.class);
broadcastIntent_one.putExtra("action", ACTION_ONE); //ACTION_TWO, ACTION_THREE
broadcastIntent_one.putExtra(EXTRA_NOTIFICATION_ID, notificationId)
// adding action for broadcast
PendingIntent broadcastPendingIntent_one =
PendingIntent.getBroadcast(application, nextRandomId(), broadcastIntent_one, PendingIntent.FLAG_UPDATE_CURRENT);
... ...
builder.addAction(null, "action one", broadcastPendingIntent_one);
builder.addAction(null, "action two", broadcastPendingIntent_two);
builder.addAction(null, "action three", broadcastPendingIntent_three);
in case of building three action buttons, the log shows some of the random numbers are same:
16:00:55.003 nextRandomId(): 400267105
16:00:55.003 nextRandomId(): 400267106
16:00:55.003 nextRandomId(): 400267106
so in the NotificationReceiver
the last two action buttons are all having the ACTION_THREE
in the extra.
what is a better way to generate a number not duplicate (no clash, efficient)?
CodePudding user response:
does it need to be random, or just be unique?
I would recommend against using uptimeMillis()
because you risk collisions every time that the system is restarted. Use the actual time instead of the uptime to reduce the chance of a collision.
Alternatively, you could use java.util.UUID.randomUUID();
. It's theoretically possible to generate a duplicate, but I wouldn't count on it.
CodePudding user response:
If you cannot have duplicates, there is nothing efficient that any random number generator can do other than saving all the numbers you've already generated and checking.
You can generate bigger and bigger random numbers to reduce the probability of duplicates -- which is what e.g. UUID
does, reducing it to extremely unlikely.
Using a Random
or SecureRandom
will probably have to be good enough, possibly combined with explicit testing to see if you already have generated a given value.
That said, if all you need is to generate IDs that do not have any duplicates on this JVM, the solution is very easy:
static final AtomicInteger counter = new AtomicInteger();
public static int getNewId() { return counter.getAndIncrement(); }
CodePudding user response:
For you application, you can consider hashing using SHA256 and then taking the last N elements. If your input is a fix string of numbers then you can expect your output to be computed in constant time as well.
See: How to hash some string with sha256 in Java?
If you're looking to assign random IDs to objects I suggest you use a GUID library. This generates a string rather than a number but you can be certain that no two will be alike.
see: https://kodejava.org/how-do-i-generate-uuid-guid-in-java/