I have a function where I have to randomly
choose an element from a HashSet
and then test if this element meets a condition. If the condition is true then return the chosen element otherwise we must randomly choose another element.
I tried the followin code:
private Number[] findClosest( int remCapacity, HashSet<Integer> remainingNodes, VrpProblem problem) {
int[] demands = problem.getDemands();
int bestNodeId = -1;
Iterator<Integer> iter = remainingNodes.iterator();
Random random = new Random();
while (iter.hasNext()) {
int nodeId = random.nextInt(remainingNodes.size());
if (demands[nodeId] > remCapacity) {
continue;
}
bestNodeId = nodeId;
}
return new Number[] {new Integer(bestNodeId)} ;
}
But it didn't work.
You are currently not reading any value from the remainingNodes
set. Depending on how expensive your solution can be, you can use the following approach:
Set<Integer>
values in a List<Integer>
instance.So the source code can look like this:
List<Integer> list = new ArrayList<Integer>(remainingNodes);
Collections.shuffle(list);
for (Integer value : list) {
if (yourCheckTestHereWith_value_andOtherVariables) {
return value;
}
}
Keep in mind that there might be a case where no value in the Set
fits your condition. You have to define a fallback case after the for
loop to handle that situation (throw exception, return null
, etc.).
One solution is to provide a method that returns a randomIterator
to iterate over the set contents. This works like a regular iterator except the elements are returned in a random order with no repeats. It works as follows:
Fischer-Yates
start shuffling the list. The shuffle algorithm proceeds, one element at a time, as next()
is called. The iterator works in O(n)
time where n
is the number of elements in the set.Set<Integer> remainingNodes =
Iterator<Integer> iter = randomIterator(remainingNodes);
while (iter.hasNext()) {
int item = iter.next();
// do the test
}
Method to return the iterator.
public static <T> Iterator<T>
randomIterator(Collection<T> collection) {
return new Iterator<T>() {
List<T> copy = new ArrayList<>(collection);
int nItems = copy.size();
public boolean hasNext() {
return nItems != 0;
}
public T next() {
int k = (int) (Math.random() * nItems);
T returnVal = copy.get(k);
copy.set(k, copy.get(--nItems));
return returnVal;
}
};
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.