## 1. Introduction

In this quick tutorial, we'll learn how to generate random numbers with no duplicates using core Java classes. **First, we'll implement a couple of solutions from scratch, then take advantage of Java 8+ features for a more extensible approach.**

## 2. Random Numbers From a Small Range

If the range of numbers we need is small, we can keep adding sequential numbers to a list until we reach size *n*. **Then, we call ***Collections.shuffle()*, which has linear time complexity. After that, we'll end up with a randomized list of unique numbers. Let's create a utility class to generate and use those numbers:

```
public class UniqueRng implements Iterator<Integer> {
private List<Integer> numbers = new ArrayList<>();
public UniqueRng(int n) {
for (int i = 1; i <= n; i++) {
numbers.add(i);
}
Collections.shuffle(numbers);
}
}
```

After constructing our object, we'll have numbers from one to *size* in random order. **Notice we're implementing ***Iterator*, so we'll get a random number every time we call *next()*. Also, we can check if we have numbers left with *hasNext()*. So, let's override them:

```
@Override
public Integer next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return numbers.remove(0);
}
@Override
public boolean hasNext() {
return !numbers.isEmpty();
}
```

Consequently, *remove()* returns the first removed item from the list. **Similarly, if we hadn't shuffled our collection, we could pass it a random index.** But, shuffling at construction time has the advantage of letting us know the whole sequence in advance.

### 2.1. Putting It to Use

To use it, we just choose how many numbers we want and consume them:

```
UniqueRng rng = new UniqueRng(5);
while (rng.hasNext()) {
System.out.print(rng.next() + " ");
}
```

This could result in output like:

`4 1 2 5 3`

## 3. Random Numbers From a Big Range

We need a different strategy if we want a more extensive range of numbers, only using a few of them. First, we cannot rely on adding random numbers to an *ArrayList* because that could generate duplicates. **So, we'll use a ***Set* because it guarantees unique items. Then, we'll use the *LinkedHashSet* implementation because it maintains insertion order.

**This time, we'll add elements to our set in a loop until we reach ***size*. Also, we'll use *Random* to generate random integers from zero to *max*:

```
public class BigUniqueRng implements Iterator<Integer> {
private Random random = new Random();
private Set<Integer> generated = new LinkedHashSet<>();
public BigUniqueRng(int size, int max) {
while (generated.size() < size) {
Integer next = random.nextInt(max);
generated.add(next);
}
}
}
```

Note we don't need to check if a number already exists in our set because *add()* does this. **Now, since we can't remove items by index, we need the help of an ***Iterator* to implement *next()*:

```
public Integer next() {
Iterator<Integer> iterator = generated.iterator();
Integer next = iterator.next();
iterator.remove();
return next;
}
```

## 4. Taking Advantage of Java 8+ Features

While custom implementations are more reusable, we can create a solution using only *Stream*s. **Starting with Java 8, ***Random* has an *ints()* method that returns an *IntStream*. We can stream it and impose the same requisites from earlier, like a range and a limit. Let's combine these features and *collect* the results into a *Set*:

```
Set<Integer> set = new Random().ints(-5, 15)
.distinct()
.limit(5)
.boxed()
.collect(Collectors.toSet());
```

The traversed set could yield output like:

`-5 13 9 -4 14`

With *ints(),* it's even simpler to have a range starting from a negative integer. **But, we must be careful not to end up with an infinite stream, which would happen if we didn't call ***limit()*, for example.

## 5. Conclusion

In this article, we wrote a couple of solutions to generate random numbers with no duplicates in two scenarios. First, we've made those classes iterable so we could easily consume them. Then, we created a more organic solution using streams.

And as always, the source code is available over on GitHub.

res – REST with Spring (eBook) (everywhere)