如何从流中获取随机对象

2022-09-01 15:32:00

假设我有一个单词列表,我想创建一个方法,该方法将新列表的大小作为参数并返回新列表。如何从原始源列表中获取随机单词?

public List<String> createList(int listSize) {
   Random rand = new Random();
   List<String> wordList = sourceWords.
      stream().
      limit(listSize).
      collect(Collectors.toList()); 

   return wordList;
}

那么我如何以及在何处可以使用我的随机?


答案 1

我找到了一个合适的解决方案。Random 提供了一些方法来返回流。例如,ints(size)它创建了一个随机整数流。

public List<String> createList(int listSize)
{
   Random rand = new Random();
   List<String> wordList = rand.
      ints(listSize, 0, sourceWords.size()).
      mapToObj(i -> sourceWords.get(i)).
      collect(Collectors.toList());

   return wordList;
}

答案 2

我认为最优雅的方式是有一个特殊的收藏家。

我很确定,您可以保证每个项目都有平等的机会被选中的唯一方法是收集,随机播放和重新流式传输。这可以使用内置的 Collectors.collectingAndThen(...) 帮助程序轻松完成。

通过随机比较器排序或使用随机化约器进行排序,就像其他一些答案所建议的那样,将导致非常偏倚的随机性。

List<String> wordList = sourceWords.stream()
  .collect(Collectors.collectingAndThen(Collectors.toList(), collected -> {
      Collections.shuffle(collected);
      return collected.stream();
  }))
  .limit(listSize)
  .collect(Collectors.toList());

您可以将该随机收集器移动到帮助程序函数:

public class CollectorUtils {

    public static <T> Collector<T, ?, Stream<T>> toShuffledStream() {
        return Collectors.collectingAndThen(Collectors.toList(), collected -> {
            Collections.shuffle(collected);
            return collected.stream();
        });
    }

}

我假设您正在寻找一种与其他流处理功能很好地集成的方法。因此,遵循简单的解决方案不是您要寻找:)

Collections.shuffle(wordList)
return wordList.subList(0, limitSize)

推荐