如果流中的流为空,如何记录消息?

给定以下 Java 8 流:


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);

在对流应用过滤并应用第一个终端操作之后,如果流为空,我想记录一条调试消息,如果不是,我想在流中的每个元素上调用该方法invoke。这可能吗?


Helenr
浏览 90回答 4
4回答

暮色呼如

您可以创建自定义Collector(此处称为StreamInterceptor),即使这并不真正符合收藏家的目的。自定义收集器将做什么?转换Stream<T>为List<T>调用 Consumer<List>,在您的情况下它将打印列表的长度。返回一个新Stream<T>的List<T>主要方法在这里,我刚刚将您的问题分解为过滤一个简单的字符串列表,并在最后将它们打印到控制台。&nbsp; &nbsp; public static void main(String[] args) {&nbsp; &nbsp; &nbsp; &nbsp; List<String> myList = List.of("first", "second", "third");&nbsp; &nbsp; &nbsp; &nbsp; myList.stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .filter(string -> !string.equals("second"))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .collect(printCount())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .forEach(System.out::println);&nbsp; &nbsp; }&nbsp; &nbsp; /**&nbsp; &nbsp; &nbsp;* Creates a StreamInterceptor, which will print the length of the stream&nbsp;&nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; private static <T> StreamInterceptor<T> printCount() {&nbsp; &nbsp; &nbsp; &nbsp; Consumer<List<T>> listSizePrinter = list -> System.out.println("Stream has " + list.size() + " elements");&nbsp; &nbsp; &nbsp; &nbsp; return new StreamInterceptor<>(listSizePrinter);&nbsp; &nbsp; }初始化时,StreamInterceptor您可以定义一个消费者,它接收从流构造的中间列表并对其执行一些操作。在您的情况下,它只会打印列表的大小。新StreamInterceptor班级import java.util.ArrayList;import java.util.Collections;import java.util.List;import java.util.Set;import java.util.function.*;import java.util.stream.Collector;import java.util.stream.Stream;class StreamInterceptor<T> implements Collector<T, List<T>, Stream<T>> {&nbsp; &nbsp; private final Consumer<List<T>> listConsumer;&nbsp; &nbsp; public StreamInterceptor(Consumer<List<T>> listConsumer) {&nbsp; &nbsp; &nbsp; &nbsp; this.listConsumer = listConsumer;&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public Supplier<List<T>> supplier() {&nbsp; &nbsp; &nbsp; &nbsp; return ArrayList::new;&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public BiConsumer<List<T>, T> accumulator() {&nbsp; &nbsp; &nbsp; &nbsp; return List::add;&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public BinaryOperator<List<T>> combiner() {&nbsp; &nbsp; &nbsp; &nbsp; return (list1, list2) -> {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; list1.addAll(list2);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return list1;&nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public Function<List<T>, Stream<T>> finisher() {&nbsp; &nbsp; &nbsp; &nbsp; return list -> {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; listConsumer.accept(list);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return list.stream();&nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public Set<Characteristics> characteristics() {&nbsp; &nbsp; &nbsp; &nbsp; return Collections.emptySet();&nbsp; &nbsp; }}

婷婷同学_

您可以peek在将列表转换为stream.public static void main(String[] args) {&nbsp; &nbsp; Stream.of(Arrays.asList(1, 2, 3), Arrays.asList(4, 5), Collections.emptyList())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .filter(x -> x.size() % 2 == 0)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .peek(s -> System.out.println(s.isEmpty()))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .flatMap(Collection::stream)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .forEach(System.out::println);}输出false45true

富国沪深

这根本不是真正的“好”,但您可以使用 peek 查看您的流并设置一个 AtomicBoolean:AtomicBoolean empty = new AtomicBoolean(true);scheduleService.list().stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .filter(Schedule::getEnabled)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .filter(this::runnable)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .flatMap(s -> s.getJobs().stream())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .peek(s -> ab.set(false);)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .forEach(this::invoke);if(empty.get()){&nbsp; &nbsp;// is Empty}

千万里不及你

您可以将您包装Stream成如下所示的自定义方法Stream<???> stream = scheduleService.list().stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.filter(Schedule::getEnabled)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.filter(this::runnable)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.flatMap(s -> s.getJobs().stream());forEachOrElse(stream, this::invoke, () -> System.out.println("The stream was empty"));随着forEachOrElse存在public <T> void forEachOrElse(Stream<T> inStream, Consumer<T> consumer, Runnable orElse) {&nbsp; &nbsp; AtomicBoolean wasEmpty = new AtomicBoolean(true);&nbsp; &nbsp; inStream.forEach(e -> {&nbsp; &nbsp; &nbsp; &nbsp; wasEmpty.set(false);&nbsp; &nbsp; &nbsp; &nbsp; consumer.accept(e);&nbsp; &nbsp; });&nbsp; &nbsp; if (wasEmpty.get())&nbsp; &nbsp; &nbsp; &nbsp; orElse.run();}我现在无法测试它,但它应该会发挥它的魔力
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java