views:

411

answers:

2

I recently found myself needing to be sure my list wasn't in order. Hibernate was nice enough to return it in perfect order. Silly hibernate, not reading my mind.

I looked at my Java API and it tells me its shuffle method does this:

Randomly permutes the specified list using a default source of randomness.

Being the curious george that I am, I want to know what exactly this means. Is there a math course I can take to learn this? Can I see the code? Java, what are you doing to my ArrayList?!?!?

To be more specific, which math concepts are being used here?

+7  A: 

Yes, you can look at the code; it basically does a Fisher-Yates shuffle. Here it is (thanks OpenJDK, and yay for open source :-P):

public static void shuffle(List<?> list, Random rnd) {
    int size = list.size();
    if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
        for (int i=size; i>1; i--)
            swap(list, i-1, rnd.nextInt(i));
    } else {
        Object arr[] = list.toArray();

        // Shuffle array
        for (int i=size; i>1; i--)
            swap(arr, i-1, rnd.nextInt(i));

        // Dump array back into list
        ListIterator it = list.listIterator();
        for (int i=0; i<arr.length; i++) {
            it.next();
            it.set(arr[i]);
        }
    }
}
Chris Jester-Young
Ah right, OpenJDK. Ok, so the "can I see the code" question was silly :). Thanks.
Stephano
Yep! :-) So, you now just need to read up on Fisher-Yates shuffle, and you're all set. :-)
Chris Jester-Young
@Chris Jester-Young Ahhhh, Fisher-Yates shuffle. That's the stuff. Wikipedia to the rescue!
Stephano
+2  A: 

The Collections JavaDoc gives some information on the shuffle method used.

This implementation traverses the list backwards, from the last element up to the second, repeatedly swapping a randomly selected element into the "current position". Elements are randomly selected from the portion of the list that runs from the first element to the current position, inclusive.

So it starts at the end and walks the list backwards. At each element it stops and swaps the current element with a preceding element from the list. The "default source of randomness" in this case is probably a Random object created with a default seed.

Bill the Lizard
How is it getting this random int?
Stephano
Where "preceding" is of a non-strict variety (i.e., each iteration can cause an item to swap with itself). :-P
Chris Jester-Young
@Stephano: If you don't specify a `Random` object, it will use `new java.util.Random()`. (This is not specified; just how the OpenJDK version works.)
Chris Jester-Young
@Chris: Thanks, I was wondering about that. The bit that I added at the end of my answer is pure speculation on my part.
Bill the Lizard