How to get a random selection of items using streams - java

Is there a way to get a random selection of items (no repeats) from a stream if you give it a random int stream?
As an example, I have a list of one thousand widgets and I want to randomly pick 25 widgets from that list. Can I do this by generating a random int stream (with numbers from 0 to 999) and using this against the widget stream?

You can do it as follows:
create an instance of Random
generate a stream of values between 0 and widgetList.size()-1 inclusive.
ensure they don't repeat (disinct)
limit to 25
grab the widget at that index
store in a list.
List<Widget> widgetList; // your populated Widget list
Random r = new Random();
List<Widget> slice =
r.ints(0,1000).distinct().limit(25).mapToObj(widgetList::get).toList();
This should work. But if the upper bound of the list (1000 in this case) is less that the limit (25) it will never terminate.
You could also just shuffle the List and take the first 25.
Collections.shuffle(widgetList);

Related

Randomize numbers from a specific array without duplicates

I have a array shuffled with some numbers I want to randomize the numbers in shuffled array without duplication am using below code
int shuffled array [] = {1,3,5,7,8}
Random random = new Random();
int random =shuffled array[random.nextInt(shuffled array.length)];
I am getting duplicate values.
How do I get to generate random number without any duplicate values?
In general you can do in of the following:
Create random numbers and keep them in a Set so that they are unique and keep pooling them until the desired amount of random numbers is achieved.
If you have a pool by which you want to pool numbers you can create an array (as you do) and then shuffle this array. Why this solution does not work for you? I think you are mixing the 2 solution and get duplicates.
Edit:
About efficiency (if you are concerned about it):
The first method uses a pseudorandom generator to produce the unique numbers. As the number of unique number in respect to the total possible numbers increases, (e.g. if you have an array and want all element to be picked up at random) then this approach might be inappropriate. If on the other hand you just want to pick 10 unique random numbers it is possibly efficient enough.
The shuffle approach as states This method runs in linear time so it should be preferred in this case (yours that is).
int pos =shuffled array[random.nextInt(4)]
int random_num_from_shuffled_array = shuffled array[pos];
Create a Collection (Set - because of the no-duplicates requirement) using your array.
Use Collections.shuffle(mySet);
You are actually using the Random class and nextInt which do not guarantee uniqueness of consecutive elements!
I guess what you need is achieved by Collections.shuffle. See the documentation

Random Number Generation in JAVA

I know about the JAVA Random class and its use. But I want to generate a random number which should not be repeated until all the numbers in the range are generated at least once. Can anybody provide me some reference..?
While using the Random class, the problem I face is that some numbers get repeated 2 or 3 times while some are not generated at all.. My application may fail in this scenario as I have another thread processing some requests based on the numbers getting generated....and the moment there is a delay and next unique digit is not available, it stops without processing the non - generated numbers...
You can generate all the values in range and shuffle them. Collections.shuffle() Once you have uses every value, repeat.
Imagine you have decks of cards, You take one deck which has a every card once, you shuffle it and you will know what while each card will come in a random order, only once. When one deck has finished you take all the cards again and reshuffle (or a new deck and shuffle that)
Create a List with all the possible random numbers in the range.
Instead of using a random number as result, use a random integer to pick an index in the list
remove it from the list and return it.
Take care to adjust the range of random integer to the current list size (it will decrease by one each time you get a new number)
you can keep a list with you of all the numbers that are already picked out and check if the new random number is in that list or not
Here is an example of someone who asked the same question

Stop randomize from picking same string in array twice in Java

Code
Random Randomizer = new Random () ;
cardoneA = suits[Randomizer.nextInt(suits.length)];
cardoneAv = ranks[Randomizer.nextInt(ranks.length)];
How can I stop the Randomizer from picking the same cards twice? Eg. If it picks a certain suit and rank, how can I stop it from picking it again? Also, how can I make it pick those two together, so that it can pick another card of the same value, as long as its a different class?
Just simulate a deck of cards like you would do it in real-life:
Store all cards which were not drawn yet in an ArrayList.
generate a random number between 0 and the current size of the ArrayList
remove the card which was picked. The array is now one less in size.
This algorithm is also known as the Fisher-Yates Shuffle.
Rather than keeping track of the card that you have picked, keep track of the card that you haven't picked, and randomize the number to choose among those that you haven't picked.
Initialize a list with all possible combination
Generate a random number within 0 to (number of unchosen cards - 1)
Pick the card and remove the card from the list
Repeat step 2 and 3 until you have necessary number of cards, or all the cards have been chosen.
You can't prevent the randomizer from returning the same index multiple times. You'll need to keep a list of which cards - a combination of suit index and rank index - have already been chosen, and pick new random indices in a loop, looping until you get a card that you haven't already picked.
Are you trying to shuffle them?
If so, the single line statement list.add(list.remove(n)); where n is a random number from 0 to list.size() - 1. Repeat this around 500 times for decent shuffling. What this does is a common shuffle; take out a random card, put it on the top.

Random Number generator to cover all numbers in the set

I am writing an Android app and I want to generate random numbers.
But, Java's RandomGenerator gives me only pseudo random numbers. The numbers repeat and not all the numbers are covered.
I want something that will give me non-repeating numbers and will cover all the numbers. How do I do that?
You can put all random values you want into a List and shuffle it.
List<Integer> numbers = ...
Collections.shuffle(numbers);
This will give you unique numbers in a random order.
You could fill a data structure with the numbers you want to loop over, then randomize the order of the elements in the structure and pull them out one by one. Alternatively, you could randomly pick indexes, and retrieve elements at those indexes. Whichever you do (you would choose the one more efficient for the specific data structure), you be sure to remove this element as you grab it. As you keep going your data structure will get smaller and smaller until you've received every element and have nothing left. This also ensures you'll never hit the same number twice, because you'll have removed it from your pool of possible numbers.

random number generation and exclusion of the generated numbers

Is it possible to do this in Java ? I want to generate a random number such that given a range say for example: between 1 and 70 - everytime the random number is generated it should be excluded from generation results.
so [1,70] rand = 56 (now 56 shouldn't be considered next time)
[1,70] = 63 (now 56,63 should be excluded from generation till my code runs)
This is equivalent to shuffling an array of numbers containing [1..70] and then dealing them out one at a time. Look up "shuffle algorithm" on Google. Here's a link http://www.vogella.de/articles/JavaAlgorithmsShuffle/article.html
I asked the same question here: How can I generate a random number within a range but exclude some?
The general strategy is something like filling an array with 70 values. Just remove the values that you randomly generate as per the link above.
you could populate the range into an array and shuffle the array. This would be inefficient though for very large ranges
Another trivial alternative, using HashMaps to keep track of random numbers.
It is sort of quick and dirty.
HashMap<Integer,Integer> hmRandomNum = new HashMap<Integer,Integer>();
Integer a = < generate random number>
if( hmRandomNum.get(a) == null)
{
hmRandomNum.put(a,a);
}
else
{
// ignore this random number. this was already selected and present in the hashmap.
}
//Iterate depending on how many numbers you want.

Categories

Resources