user1759136
user1759136

Reputation:

Create Java Random from the size of the List

I have created a method to randomize the list:

public <T> List<T> randomize(List<T> list) {
    LinkedList<T> randomizedList = new LinkedList<>();
    Random random = new Random(list.size());
    for (int i = random.nextInt(); i < list.size(); i++) {
        randomizedList.add(list.get(i));
    }
    return randomizedList;
}

The list that I am passing to this method contains for e.g. five elements. When I am creating Random random = new Random(list.size()); I expect so when I call random.nextInt() what it will return me the random integer which will be an index of the list element.

But when I call random.nextInt(); instead of returning the number from the interval [0, 4] (which I expect to be returned) it returns me the value of for e.g.: -349120689. Which gives me an java.lang.IndexOutOfBoundsException: Index: -349120689, Size: 5.

Why is this happening and how to solve this?

Upvotes: 0

Views: 4137

Answers (5)

Simon Forsberg
Simon Forsberg

Reputation: 13331

  1. new Random(list.size()); this sets the seed of the Random number generator to list.size(); I suggest changing to new Random() (which will give you a seed based on the current time of the system). Preferably though, you'd want to reuse the same Random object at all times.

  2. random.nextInt(); here is where you'd want to put random.nextInt(list.size()); which will give you a number from 0 to list.size() - 1.

  3. Even with the above changes, your code would just give you a sublist of the list starting at a random index and going until the end. Use Collections.shuffle(list) instead.

To do a real shuffling, you would need to "remember" which elements you have inserted or not. In pseudo-code, you could do the following:

  • Copy the original list to a new one, let's call it "orig"
  • Create a new, empty, list, let's call it "result"
  • As long as the orig list has elements, get an element at random index and add it to the result list. Remove the chosen element from orig list.
  • Return result list.

Upvotes: 3

Jon Skeet
Jon Skeet

Reputation: 1500065

I expect so when I call random.nextInt() what it will return me the random integer which will be an index of the list element.

You've misunderstood the purpose of the Random(long) constructor. The purpose of that constructor is to specify a seed for the list. You don't want to do this - it would mean that every collection of size 5 is always shuffled the same way.

You specify the range on each call to nextInt. So if you want a random number between 0 (inclusive) and max (exclusive) you just use:

int value = random.nextInt(max);

However, it would be much better just to use Collections.shuffle instead of writing your own code to do this - assuming you really want a shuffle (which isn't what your current approach would give you anyway - even after fixing the nextInt call, you'd end up with basically a sublist, because nextInt() is only called once. So if the first call to nextInt() returns 2 (in a list of 5) you'd end up returning a new list containing the final 3 elements. I strongly suspect that's not what you were trying to do.

As a side-note, when you want to know why an API isn't behaving the way you expect it to, read the documentation. The documentation of the Random(long) constructor and Random.nextInt() are pretty clearly not the behaviour you were expecting.

Upvotes: 2

onon15
onon15

Reputation: 3630

You're confusing the argument to nextInt(n) (upper bound for the randomization) with the argument to the constructor (random seed). You shoudl use nextInt(list.size), and probably, initialize the Random object using new Random().

Upvotes: 0

The argument to the Random constructor is a random seed, not the maximum of what it returns.

Pass the maximum number to nextInt() instead.

Upvotes: 0

muluturk
muluturk

Reputation: 63

use this

public <T> List<T> randomize(List<T> list) {
    LinkedList<T> randomizedList = new LinkedList<>();
    Random random = new Random();
    for (int i = random.nextInt(list.size()); i < list.size(); i++) {
        randomizedList.add(list.get(i));
    }
    return randomizedList;
}

Upvotes: 0

Related Questions