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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With