Choosing random numbers efficiently
You can try using an existing Java implementation (or this one) for a Mersenne Twister.
Keep in mind most MT's are not cryptographically secure.
It looks like you want to select a k-combination from a set S without replacement, with S having n distinct values, k = 5 and n = 52. You can shuffle()
the entire set and select k elements (as @Tesserex suggests), or pick()
k elements while avoiding duplicates (as you've shown). You'll want to profile both in your particular environment and for your chosen generator. I often, but not always, see a modest edge for pick()
.
private static final Random rnd = new Random();
private static final int N = 52;
private static final int K = 5;
private static final List<Integer> S = new ArrayList<Integer>(N);
static {
for (int i = 0; i < N; i++) {
S.add(i + 1);
}
}
private final List<Integer> combination = new ArrayList<Integer>(K);
...
private void shuffle() {
Collections.shuffle(S, rnd);
combination.addAll(S.subList(0, K));
}
private void pick() {
for (int i = 0; i < K; i++) {
int v = 0;
do {
v = rnd.nextInt(N) + 1;
} while (combination.contains(v));
combination.add(v);
}
}
A common technique is to start with a list of all the possible inputs, and randomly select from that, deleting ones as you go. That way there's no risk of selecting a duplicate and having to loop for an unknown amount of time. Of course this method only works with discrete data, but fortunately integers are. Also remember that your list (or other data structure) selection and deletion should be O(1) if possible, since you're focusing on speed.
You could use linear congruence as a random generator: http://en.wikipedia.org/wiki/Linear_congruential_generator [yet consider their statistical disadvantages]
You only need a calculation of (x + c) % m for each number. Yet, in my experience the creation of objects (like you might do with every call of new Set and add, depending on which implementation you use) might cost you more speed than a call to nextInt(). Maybe you should try a profiler like e.g. this one: http://www.eclipse.org/tptp/
I don't have any input on your actual problem, and I don't know too much Java (just poking around). However it seems to me that you are trying to build a hand evaluator for poker and this thread http://pokerai.org/pf3/viewtopic.php?f=3&t=16 contains some extremely fast java hand evaluators. Hopefully some of this code could be of help.