HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaModerate

Picking 10 distinct words 'randomly' from List of unique words

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
distinctuniquepickingwordsrandomlylistfrom

Problem

My goal is to pick 10 unique words randomly from a List containing 20 unique words.

I would remove the duplicate word from the List whenever a duplicate word is added and decrement the for loop counter by 1.

List words = new ArrayList();
/* code to add 20 words */

List word10 = new ArrayList();
for (i = 0; i < 10; i++) {
  int randomIndex = new Random().nextInt(words.size());
  if (word10.contains(words.get(randomIndex)) == true) {
    word10.remove(words.get(randomIndex));
    i--;
  }
  word10.add(words.get(randomIndex));
}
System.out.println("word10 List: " + word10);


Output

word10 List: [aah, abalone, aback, abandonee, abandonedly, abandon, abacus, aahed, aardvarks, abacuses]
word10 List: [a, aardvarks, aahing, abalones, abacuses, aahed, abacus, aah, abaft, abandoned]
word10 List: [abalones, ab, abaci, a, abacuses, abandonedly, aah, aahs, aardwolf, aardvark]


The code given is working properly. Is there a better approach?

Solution

First off, don't make a new Random instance every iteration.

Secondly your approach is ineffective for larger numbers, and especially if the number of words to choose is closer to the number of words available. The odds that a word is not already among the chosen words can become so small it can take a long time for your code to complete. Imagine picking 1.000.000 words in random order from a list of 1.000.000, getting the last word is a 1 in a million chance to get right.

A simple but more efficient approach is to shuffle the words and then just take the head of the list :

List words = new ArrayList();
/* code to add 20 words */

Collections.shuffle(words);

System.out.println("word10 List: " + words.subList(0, 10));


Obviously you don't need to shuffle the entire list. You can write your own partial Fisher-Yates shuffle (basically swap your choices to the head of the list), that stops once enough of the list is shuffled. This is definitely a good choice if you're going to do this for large collections of words with only a small list to choose.

Code Snippets

List<String> words = new ArrayList<String>();
/* code to add 20 words */

Collections.shuffle(words);

System.out.println("word10 List: " + words.subList(0, 10));

Context

StackExchange Code Review Q#146551, answer score: 11

Revisions (0)

No revisions yet.