É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 Réponses :
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.
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
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
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 }
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.
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); }
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 des.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}