Google's Guava library provides a great class called Range
, it has many useful methods like greaterThan(x)
, open(x,y)
, etc. I am wondering if there is any way of applying such method to generate a random number within a Range
?

- 47,227
- 18
- 148
- 244

- 1,880
- 1
- 16
- 21
-
1I see no such method on http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Range.html. What have you tried? – Jul 02 '14 at 15:33
-
2What's wrong with `Random.nextXXX`? – Boris the Spider Jul 02 '14 at 15:37
-
No, there's not really a way to do this. – Louis Wasserman Jul 02 '14 at 15:46
-
@BoristheSpider nothing, but you may already have a `Range` object and want a value from within that range. Extracting a random value isn't complicated, but it isn't totally obvious. – dimo414 Apr 28 '16 at 15:25
2 Answers
I would not suggest using a range for this basic application.
The easiest method to use is the already implemented Random class.
Here is how to use the class:
For getting a random integer of any value:
Random r = new Random();
r.nextInt();
For getting a random integer in a range of min x, max y:
Random r = new Random();
r.nextInt(y - x) + x;
This is the most basic way of getting a random number in a range. I bet there is a getMin and getMax method in the range class, so use that for x and y.
Also, if you want a random number greater than a min value of x, just do:
Random r = new Random();
Math.abs(r.nextInt().nextInt()) + x;
^The code above generates any positive integer, and the x ensures the min value.
-or-
nextInt(Integer.MAX_VALUE - (x + 1)) + (x + 1)
-as suggested by ColinD Hope this helps. -Classic

- 3,160
- 3
- 16
- 25
-
1`new Random().nextInt() + x` won't do what you describe, since `nextInt()` can return any `int` value including negative values and values that are greater than `Integer.MAX_VALUE - x`. I think you'd need `nextInt(Integer.MAX_VALUE - (x + 1)) + (x + 1)` if you want the value to be strictly _greater than_ `x`. – ColinD Jul 02 '14 at 16:04
-
Using `new Random()` just once is wrong (too inefficient and badly distributed). Even in an example, please write just `random.nextInt()`. And ColinD is right, so please fix this, too. – maaartinus Jul 02 '14 at 16:59
-
Slight correction: the result of `Math.abs(r.nextInt())` can actually be negative if the RNG happens to produce `Integer.MIN_VALUE`. – Hakanai Apr 16 '21 at 00:33
Like Louis says there's no built-in way to do this, but there are a couple of fairly straightforward options. Note that we have to assume all Range
instances are bounded on both sides - you cannot select a random value from an unbounded or non-discrete range (e.g. (-∞..0]
).
The easiest to implement solution is to simply convert the Range
into a ContiguousSet
, from which you can select a random value in linear time. This has the advantage of working for any discrete type, not just Range<Integer>
.
public static C random(Range<C> range, DiscreteDomain<C> domain) {
Set<C> set = ContiguousSet.create(range, domain);
int index = random.nextInt(set.size());
return Iterables.get(set, index);
}
Of course constant time would be better, especially for large ranges. Canonicalizing the Range
first reduces the number of cases we have to handle, and we can use the f(y-x) + x
pattern JClassic suggests.
public static int random(Range<Integer> range) {
checkArgument(range.hasLowerBound() && range.hasUpperBound(),
"Cannot select a random element from unbounded range %s", range);
Range<Integer> canonical = range.canonical(DiscreteDomain.integers());
return random.nextInt(canonical.upperEndpoint() - canonical.lowerEndpoint())
+ canonical.lowerEndpoint();
}
You can extend this easily for Long
with Random.nextLong()
(but note that Random.nextLong()
cannot return all long
values, so SecureRandom
would be preferable).