Instead of using such a custom method, I recommend you use OOTB Collections.shuffle. Check this to understand the logic implemented for Collections.shuffle
.
Analysis of your code:
Math.random() returns a double
value with a positive sign, greater than or equal to 0.0
and less than 1.0
.
Now, let's assume numbers.size() = 5
and dry run the for
loop:
When i = 0, index = (int) (0 + Math.random()*(5 - 0)) = (int) (0 + 4.x) = 4
When i = 1, index = (int) (1 + Math.random()*(5 - 1)) = (int) (1 + 3.x) = 4
When i = 2, index = (int) (2 + Math.random()*(5 - 2)) = (int) (2 + 2.x) = 4
When i = 3, index = (int) (3 + Math.random()*(5 - 3)) = (int) (3 + 1.x) = 4
When i = 4, index = (int) (4 + Math.random()*(5 - 4)) = (int) (4 + 0.x) = 4
As you can see, the value of index
will remain 4
in each iteration when numbers.size() = 5
.
Your queries:
how does this ensure that: i) we won't get an out of bounds index
As already explained above using the dry run, it will never go out of bounds.
or ii) I won't be changing the same element's i.e. index == i and the
shuffle would not be that random?
swap(numbers, i, index);
is swapping the element at index, i
with the element at index, 4
each time when numbers.size() = 5
. This is illustrated with the following example:
Let's say numbers
= [1, 2, 3, 4, 5]
When i = 0, numbers will become [5, 2, 3, 4, 1]
When i = 1, numbers will become [5, 1, 3, 4, 2]
When i = 2, numbers will become [5, 1, 2, 4, 3]
When i = 3, numbers will become [5, 1, 2, 3, 4]
When i = 4, numbers will become [5, 1, 2, 3, 4]