Creating Random Numbers With No Duplicates in Java – 在Java中创建无重复的随机数

最后修改: 2022年 9月 18日

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.

在这个快速教程中,我们将学习如何使用核心Java类生成无重复的随机数。首先,我们将从头开始实现几个解决方案,然后利用Java 8+的功能来获得更多的扩展性。

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


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:


public Integer next() {
    if (!hasNext()) {
        throw new NoSuchElementException();
    return numbers.remove(0);

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( + " ");

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 =;
    return next;

4. Taking Advantage of Java 8+ Features

4.利用Java 8+功能的优势

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:

虽然自定义的实现更具可重用性,但我们可以只使用Streams创建一个解决方案。从Java 8开始,Random有一个ints()方法,可以返回一个IntStream。我们可以将其流化,并施加与先前相同的必要条件,如范围和限制。让我们结合这些功能,并将结果收集到Set

Set<Integer> set = new Random().ints(-5, 15)

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.