Yupie Yupie - 7 months ago 17
Java Question

Getting a random object from a random amount

I have a small issue with a project I'm working on,

I have a list of a "Location" object, the size of this list is variable and depends on the users input. (getAllRed(arena) is a method that returns a list of locations).

What I want is to get a random location from this list and do something with it. I seem to be stuck here as the "amount" is a variable, usually, I use the following:

Random rnd = new Random();
int i = 0;

for (int fi = 1; fi <= 1; fi++) {
i = 1 + rnd.nextInt(1);
if (i == 1) {
// do something
}
else {
//do something else
}
}


But, because in my case the integer that goes in rnd.nextInt(HERE); is variable, depending on the size of the list, I can't use this.

How could I solve this?

This is the code I have right now:

int amount = getAllRed(arena).size();

Random rnd = new Random();
int i = 0;

for (int fi = 1; fi <= 1; fi++) {
i = 1 + rnd.nextInt(amount - 1 );
}


The amount - 1 is needed because Java will start at "0" I believe.

Let's say the list contained 3, this is how it would look:

int amount = getAllRed(arena).size();

Random rnd = new Random();

int i = 0;

for (int fi = 1; fi <= 1; fi++) {
i = 1 + rnd.nextInt(amount - 1 );
if(i == 0){
return getAllRed(arena).get(0);
}
else if( i == 1){
return getAllRed(arena).get(1);
}
else{
return getAllRed(arena).get(2);
}
}

Answer

You should do this:

int amount = getAllRed(arena).size();    

Random rnd = new Random();
for (int fi = 1; fi <= 1; fi++) {
    int i = rnd.nextInt(amount);
    return getAllRed(arena).get(i);
}

rnd.nextInt(amount) will return an int in the range [0, amount). (That's 0, inclusive and amount, exclusive.)

However, you really shouldn't call getAllRed(arena) multiple times. (I don't know if the function is functionally pure or not.)

// assuming that getAllRed(arena) returns a List<MyType>
List<MyType> allRed = getAllRed(arena); 
Random rnd = new Random();
for (int fi = 1; fi <= 1; fi++)
    return allRed.get(rnd.nextInt(allRed.size()));

Another note is that return will break out of the for loop, so there's no point in even having it:

// assuming that getAllRed(arena) returns a List<MyType>
List<MyType> allRed = getAllRed(arena); 
Random rnd = new Random();
return allRed.get(rnd.nextInt(allRed.size()));

Yet another note is that your Random rnd should be kept somewhere global so that it won't be reseeded every time you use this function (perhaps with the same seed every time, which would make this not be random).