Whereas the shuffle method works, there is another way that doesn't require modifying the original array. In fact, you don't even need to know how many total items there are. You can pick M items at random from a stream, and the only data you have to save is an array of those M items.
The basic idea is an extension of the algorithm for picking a single item from a stream of unknown length. Again, you don't know how many items are in the stream. So you always have a selected item, but you might change the selected item at any time.
You start by having no selected item, and a count of 0. When the first item comes in, you increase the count. Then you pick a random number in the range 0 to count-1. If the value is 0, then you make the current item the selected item. The first random number picked has to be 0 because your range is 0 to 0.
As you read each item, you increase the count, pick the random number, and make the current item the selected item if the random number picked is 0. It looks like this:
selected_item = none
count = 0
for each item
count = count + 1
if (random(count) == 0)
selected_item = current_item
This works because the chance of selecting the current item decreases as each item is read. That is, the first item is selected with probability 1/1. When the second item comes in, there is a 1/2 chance that you will select it to replace the first item. When you receive the third item, there is a 1/3 chance that you will replace the currently selected item with the new item.
When you reach the end of the stream, you will given every item an equal chance at having been selected.
You can extend that to multiple items pretty easily. You start by selecting the first M items that come in, and placing them in your selected items array. Then, whenever a new item comes in you pick a random number between 0 and count-1, and if that number is less than M, then you randomly replace one of the selected items with the new item. It looks something like this:
selected_items = array of M items
count = 0
for each item
if (count < M)
selected_items[count] = current_item
else
if (random(count) < M)
// pick a random number from 0 to M-1
// and replace that item with the new item
ix = random(M)
selected_items[ix] = current_item
I wrote more detail about this in my blog, Random selection.