Okay, so this method is probably a bit ugly, but it works great:
I start by defining the probability of each cell type. For simplicity's sake, everything is a percentage, with the sum of all values adding up to 100:
1 2 3 4
 int chanceForEmpty = 70; int chanceForBig = 10; int chanceForMedium = 15; int chanceForSmall = 5; 
Then I run a loop for each chance variable, adding it into a values array as many times as it's needed. This array will contain all of the chance values:
1 2 3 4 5 6 7 8 9 10 11 12
 int valueSum = chanceForEmpty + chanceForBig + chanceForMedium + chanceForSmall;
int[] values = new int[valueSum];
int iteration = 0; for (int i = 0; i < chanceForEmpty; i++) { values[iteration] = 0; iteration++; } for (int i = 0; i < chanceForBig; i++) { values[iteration] = 1; iteration++; } for (int i = 0; i < chanceForMedium; i++) { values[iteration] = 2; iteration++; } for (int i = 0; i < chanceForSmall; i++) { values[iteration] = 3; iteration++; }

Now, when I want to get a random, weighted type for a particular cell, I can call up a random value in the lookup array, which provides the weighting / probabilities I need:
1 2 3
 Random rnd = new Random(); int index = rnd.nextInt(values.length); int randomType = values[index]; 
I know the more talented guys and gals out there think this is probably ugly. I accept that this is only really useful in situations where the resulting precomputed lookup array is fairly small. Mine is only 100 elements in size, but much larger sets could have memory footprint issues. But go gentle, this is my first attempt at handling weighted random selection
There's also the fact that this is precomputed, so obviously there would be additional issues on massive sets whilst everything is being preloaded into the lookup array. But again, my array size is small enough to be fairly inconsequential.
Here's my summary of what I've learned from this experiment:
PROS:
 Probably the easiesttounderstand method of accomplishing this that I've reviewed thus far.
 Quick and easy to code from the groundup
 Since everything is precomputed, onthefly random selection requires no more work that fetching a value from memory.
CONS:
 Probably an ugly way to solve this!
 Adding a new weighted value to the set requires a little bit of coding (new
for loop)
 Requires some recalculation of how it affects the probabilities of other items in the set
 Not suitable for massive datasets (potentially memoryhungry, requires precomputation).
I hope someone else finds this useful.
Thanks everybody for your help on this today!