30 votes

Pourquoi Stream.limit ne fonctionne-t-il pas comme prévu dans cet extrait ?

List<Integer> integer = Stream.generate(new Supplier<Integer>() {
    int i = 0 ;

    @Override
    public Integer get() {
        return ++i;
    }
}).filter(j -> j < 5)
  .limit(10)   // Note the call to limit here
  .collect(Collectors.toList());

Contrairement à ce que je pensais, le collect L'appel ne revient jamais. Réglage de limit avant filter produit le résultat attendu. Pourquoi ?

30voto

Eran Points 35360

Comme il n'y a que 4 éléments qui passent le filtre, limit(10) n'atteint jamais 10 éléments, donc le pipeline Stream continue à générer de nouveaux éléments et à les alimenter au filtre, en essayant d'atteindre 10 éléments qui passent le filtre, mais comme seuls les 4 premiers éléments passent le filtre, le traitement ne se termine jamais (au moins jusqu'à ce que i débordements).

Le pipeline Stream n'est pas assez intelligent pour savoir que plus aucun élément ne peut passer le filtre, il continue donc à traiter de nouveaux éléments.

25voto

Mureinik Points 61228

Retourner le limit et le filter a des comportements différents.

Si vous mettez le limit Tout d'abord, le flux va générer 10 entiers [1..10], puis les filtrer en ne laissant que ceux qui sont inférieurs à 5.

Dans la commande initiale, avec le filter appliqué en premier lieu, des entiers sont générés et filtrés jusqu'à ce que vous atteigniez 10 éléments. Il ne s'agit pas d'un opérateur infini, car i dans le fournisseur finira par déborder, mais cela prendra un certain temps, surtout sur un ordinateur lent, pour arriver à MAX_INT .

16voto

Tagir Valeev Points 14218

Si vous voulez arrêter soit si le numéro 5 est atteint ou si 10 éléments sont collectés, il y a Stream.takeWhile() ajoutée en Java-9 :

List<Integer> integer = Stream.generate(new Supplier<Integer>() {
    int i = 0 ;

    @Override
    public Integer get() {
        return ++i;
    }
}).takeWhile(j -> j < 5).limit(10).collect(Collectors.toList());

9voto

Oliv Points 828

Il se terminera, après que le fournisseur ait débordé et commencé à générer des nombres négatifs. La liste résultante contiendra :

[1, 2, 3, 4, -2147483648, -2147483647, -2147483646, -2147483645, -2147483644, -2147483643]

La raison en est dans d'autres réponses. Sur ma machine i7, il a fallu 40 secondes pour terminer.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X