 ## 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++) {
}

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);
}
}
}``````

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 Streams. 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.

### Get started with Spring 5 and Spring Boot 2, through the Learn Spring course:

>> CHECK OUT THE COURSE 