Reputation: 1559
Lets say we have:
private List<Item> items = new ArrayList<Item>();
where Item
is my custom class, which can have two states (boolean) active (true) or not active (false) it has boolean isActive()
which returns current state.
Now what I am trying to do, is to receive random item from the list (from 0 to items.size() - 1)
but it has to be active.
What I was thinking to do is to after getting random item from the list, check if its active, and if not, repeat till we receive active item, if its active, return it so we can use it.
Not sure if its right approach, thanks.
Upvotes: 1
Views: 837
Reputation: 129537
The problem I have with your suggested approach is that it can become very inefficient under certain conditions, particularly when you have very few active Item
s in your list. Another idea would be to create a new list containing the indexes of all of the active Item
s in the items
list:
List<Integer> indexes = new ArrayList<Integer>(items.size());
for (int i = 0; i < items.size(); i++)
if (items.get(i).isActive())
indexes.add(i);
Then you simply need a random element from indexes
, and would refer to the Item
in items
at that particular location. So your random active element would be
items.get(indexes.get((int)(Math.random() * indexes.size())))
Upvotes: 6
Reputation: 3178
I think it would give you more control by iterating through the list and collecting all active Items into a new list.
private List<Item> activeItems = new ArrayList<Item>();
foreach (Item x in items)
{
if (x.Isactive) activeItems.Add(x);
}
Once you've got the list of only active items, get a random position from that list.
Upvotes: 1
Reputation: 7804
Try this out :
List<CustomClass> list = new ArrayList<CustomClass>();
Random random = new Random();
while (true) {
int nextInt = random.nextInt();
if (nextInt > 0 && nextInt <= list.size()) {
if(list.get(nextInt).isActive()){
// Current state is active
System.out.println("Found active");
break;
}
}
}
Upvotes: 0
Reputation: 4727
You can extend ArrayList
and create a method that returns a new ArrayList
(or other Collection
maybe) only with active items.
class MyItemArrayList extends ArrayList {
public ArrayList getActiveItems() {
ArrayList<Item> activeArrayList = new ArrayList<>();
for (Item item : this) {
if (item.isActive()) {
activeArrayList.add(item);
}
}
return activeArrayList;
}
}
Upvotes: 0
Reputation: 33283
That depends on the ratio between active and inactive items. If most items are expected to be active, then go with your idea, otherwise you can go woth A.R.S' solution.
Note:
There is a caveat with the retry approach. If all items are inactive you will end up with an infinite loop.
Upvotes: 1