Comment obtenir des objets aléatoires à partir d'un flux
Permet de dire que j'ai une liste de mots et je veux créer une méthode qui prend la taille de la nouvelle liste en paramètre et retourne la nouvelle liste. Comment puis-je obtenir des mots au hasard de mon sourceList?
public List<String> createList(int listSize) {
Random rand = new Random();
List<String> wordList = sourceWords.
stream().
limit(listSize).
collect(Collectors.toList());
return wordList;
}
Oui, comment et où puis-je utiliser ma Aléatoire?
- Est-il une raison pour utiliser un
Stream
? Ne pouvez-vous pas aléatoire de la liste d'origine, et ensuite de retour une copie avecsubList
? - Savez-vous combien de mots dans le cours d'eau de source?
- Ce Que @AlexisC. dit.
Collections.shuffle
etlist.subList(0,size)
devrait être suffisant. - Voir aussi cette réponse, si il y a un grand nombre d'éléments qui pourraient faire brassage cher: stackoverflow.com/a/28655112/1441122
Vous devez vous connecter pour publier un commentaire.
J'ai trouvé une solution adéquate.
Aléatoire fournit quelques méthodes de retour d'un flux. Par exemple ints(taille), ce qui crée un flux d'entiers aléatoires.
rand.ints(0, sourceWords.size()).distinct().limit(listSize).mapToObj(sourceWords::get)
serait mieux.Limit()
est tout simplement ignoré dans ce cas.Je pense que la façon la plus élégante est d'avoir un collecteur spécial.
Je suis assez sûr que la seule façon vous pouvez garantir que chaque élément a une chance égale d'être choisi, est de collecter, shuffle et re-stream. Cela peut être fait facilement à l'aide intégrée dans les Collecteurs.collectingAndThen(...) helper.
Tri par hasard comparateur ou à l'aide de randomisée réducteur, comme l'a suggéré sur certains autres réponses, va entraîner très biaisée de l'aléatoire.
Vous pouvez déplacer brassage collecteur à une fonction d'assistance:
Je suppose que vous êtes à la recherche d'un moyen de bien s'intégrer avec les autres fonctions de traitement de flux. Donc suivant simplement la solution n'est pas ce que vous cherchez 🙂
C'est ma seule solution en ligne:
RandomUtils sont de commons lang 3
Voici une solution je suis venu avec ce qui semble être différente de toutes les autres, alors je me suis dit pourquoi ne pas ajouter à la pile.
Fondamentalement, il fonctionne en utilisant le même genre de truc qu'une itération de
Collections.shuffle
chaque fois que vous demandez à l'élément suivant - choisir un élément aléatoire, swap de cet élément avec le premier de la liste, déplacez le pointeur vers l'avant. Pourrait aussi le faire avec le pointeur en commençant par la fin.Le problème, c'est qu'il ne fait muter la liste que vous avez passé, mais je suppose que vous pouvez simplement prendre une copie que la première chose si vous n'aimez pas ça. Nous étions plus intéressés par la réduction des copies redondantes.
Collections.swap
trop.Essayer quelque chose comme ça:
La réponse est très simple(avec stream):
Vous pouvez tester:
Collections.shuffle()
: pour toutes les deux éléments dans cette liste, on vient avant l'autre chaque fois que vous consultez. Et sûrement, d'un élément par rapport à lui-même, les rendements de l'égalité. Votre comparateur de ne retourne jamais à zéro.Collections.shuffle()
pourList<String> src
de mon exemple, et ce, pour deux éléments à chaque fois qu'ils sont dans un ordre différent. Peut-être que j'ai mal compris vous?shuffle()
de nouveau à chaque fois. Je l'ai mentionné une liste qui a été traitée parshuffle
une fois et ensuite inspecté. Cette liste a une au hasard, mais certain ordre, et l'équivalent de qu'est ce que l'OP besoins. Votre solution c'est comme traînant toute la liste à chaque fois que vous appeleziterator.next()
List<String> src = IntStream.range(0, 100000).mapToObj(String::valueOf).collect(Collectors.toList());
. Utiliser, par exemple, 0 graine (Random r = new Random(0);
) et il va se planter.Comparator
contrat. Vous pouvez vous attendre à chaque méthode à l'aide d'un comparateur à détester rupture de contrat. I. e.Collections.sort
se comporte de la même, même sous Java 7.