4
votes

Comment enregistrer un message si un flux est vide dans le flux?

Étant donné le flux Java 8 suivant:

scheduleService.list().stream()
                      .filter(Schedule::getEnabled)
                      .filter(this::runnable)
                      .flatMap(s -> s.getJobs().stream())
                      // .doSomethingArbitrary(System.out.println("A single message. The total number of 
                      // elements in the stream after filtering is " + this::count))
                      .forEach(this::invoke);

Une fois le filtrage appliqué au flux et après l'application de la première opération de terminal, je voudrais soit enregistrer un message de débogage si le flux est vide ou s'il ne l'est pas, appelez la méthode invoke sur chaque élément du flux. Est-ce possible?


4 commentaires

Pouvez-vous expliquer ce que vous entendez par après l'application de la première opération de terminal ? Il n'y a qu'une seule opération de terminal dans le flux ci-dessus, c'est-à-dire forEach . Que diriez-vous d'un code Java7 correspondant à votre tâche souhaitée? Rendrait les choses beaucoup plus claires à mon humble avis.


@Naman J'ai modifié mon exemple de code. Est-ce que cela rend les choses plus claires?


@crmepham non, ce n'est pas le cas. ce dont nous sommes confus est ceci après la première opération de terminal - puisqu'il n'y a qu'une seule opération de terminal ... Il me semble que ce que vous essayez d'expliquer ici est: si le Stream est vide < i> après ce filtre - vous voulez enregistrer un message; sinon vous voulez traiter tous les jobs de s.getJobs (). stream () en appelant la méthode invoke; si c'est simplement:


List list = scheduleService.list () .stream () .filter (Schedule :: getEnabled) .filter (this :: runnable) .flatMap (s -> s.getJobs (). stream ()) .collect (Collectors.toList ()); if (list.isEmpty ()) {consigner ce message;} else {traiter via invoke}


4 Réponses :


0
votes

Vous pouvez toujours définir un mappeur personnalisé qui effectue la journalisation:

 // same
.flatMap(SomeClass::loggingMapper)

Puis

public static Stream<Job> loggingMapper(Service service) {
    if( service.getJobs().isEmpty() ) {
        System.out.println("Empty!"); // Or some other logging code
    }
    return service.getJobs().stream();
}

Dans tous les cas, votre mappeur doit retourner un flux.


3 commentaires

cela sera enregistré une fois à chaque fois qu'un service n'a pas de travaux. il n'enregistre pas s'il n'y a aucun travail au total


La question est "si un flux est vide dans le flux , j'ai donc pensé que l'OP signifiait les flux de travaux pour chaque service.


Vrai. Je n'ai pas vu le titre de la question. Le titre semble contracter le corps de la question. J'ai apporté une modification insignifiante à votre message afin de pouvoir supprimer mon vote défavorable



0
votes

Vous pouvez envelopper votre Stream dans une méthode personnalisée comme la suivante

public <T> void forEachOrElse(Stream<T> inStream, Consumer<T> consumer, Runnable orElse) {
    AtomicBoolean wasEmpty = new AtomicBoolean(true);
    inStream.forEach(e -> {
        wasEmpty.set(false);
        consumer.accept(e);
    });

    if (wasEmpty.get())
        orElse.run();
}

Avec forEachOrElse étant

Stream<???> stream = scheduleService.list().stream()
                                           .filter(Schedule::getEnabled)
                                           .filter(this::runnable)
                                           .flatMap(s -> s.getJobs().stream());

forEachOrElse(stream, this::invoke, () -> System.out.println("The stream was empty"));

Je ne peux pas le tester pour le moment mais il devrait faire sa magie


0 commentaires

0
votes

Ce n'est pas vraiment "sympa" du tout, mais vous pouvez utiliser peek pour regarder dans votre flux et définir un AtomicBoolean:

AtomicBoolean empty = new AtomicBoolean(true);

scheduleService.list().stream()
                      .filter(Schedule::getEnabled)
                      .filter(this::runnable)
                      .flatMap(s -> s.getJobs().stream())
                      .peek(s -> ab.set(false);)
                      .forEach(this::invoke);

if(empty.get()){
   // is Empty
}


2 commentaires

Comment définir le booléen empty sur true si le flux est vide?


Le booléen est vrai au début. mais si un travail existe, il le mettra à false et ensuite si le booléen est mis à true, le journal se produira.



0
votes

Vous pouvez ajouter un aperçu avant de convertir la liste en stream.

false
4
5
true

Sortie p>

public static void main(String[] args) {
    Stream.of(Arrays.asList(1, 2, 3), Arrays.asList(4, 5), Collections.emptyList())
            .filter(x -> x.size() % 2 == 0)
            .peek(s -> System.out.println(s.isEmpty()))
            .flatMap(Collection::stream)
            .forEach(System.out::println);
}


0 commentaires