Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Quick way of creating a random subset of an array using IntStream

I am wondering if IntStream and lambdas can be used somehow to quickly (one-line) create an array containing a random subset of an existing array of elements.

For example, say I have a pool of players:

Player[] allPlayers;

And I want to get a random subset of those players, given the dimension of the required subset. Traditionally I would do something like:

List<Player> players = new ArrayList<Player>(Arrays.asList(allPlayers));

int subsetSize = 8;
Player[] subset = new Player[subsetSize];
for (int i = 0; i < subsetSize; i++) {
  int randIndex = new Random().nextInt(players.size());
  subset[i] = players[randIndex];

  players.remove(randIndex);
}

return subset;

But can this process be done with Java 8 features? Which I assume would make it more condensed, which is what I am trying to achieve. I am still getting the hang of these new Java 8 features, like IntStream and lambdas and I wouldn't know how to use them for this particular case.

like image 945
dabadaba Avatar asked Oct 17 '25 19:10

dabadaba


1 Answers

In this case, you want to select streamSize distinct elements from an input array.

You can use the Random#ints(randomNumberOrigin, randomNumberBound) method:

Returns an effectively unlimited stream of pseudorandom int values, each conforming to the given origin (inclusive) and bound (exclusive).

This returns a stream of random integers in the specified range. To ensure distinct values, distinct() is called and limit(...) allows to only keep the number of elements we want.

Random random = new Random();
Player[] subset = random.ints(0, allPlayers.length)
                        .distinct()
                        .limit(subsetSize)
                        .mapToObj(i -> allPlayers[i])
                        .toArray(Player[]::new);

I would note however, that, even if this is a one-liner, it is not as efficient as JB Nizet's solution since this continues generating integers until a distinct one is found.

like image 56
Tunaki Avatar answered Oct 20 '25 09:10

Tunaki



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!