How to break the foreach of java8 stream

How to break the foreach of java8 stream

brief introduction

We usually need to traverse and process the data in Java stream, and foreach is the most commonly used method.

But sometimes we don't want to process all the data, or sometimes the stream may be very long or infinite at all.

One method is to first filter out the data we need to process, and then foreach traversal.

So how do we break the stream directly? Today, this article focuses on this problem.

Using splitter

In the previous article, when we talked about the splitter, we mentioned that in the tryadvance method, if false is returned, the splitter will stop processing subsequent elements.

Through this idea, we can create a custom splitter.

If we have such a stream:

Stream<Integer> ints = Stream.of(1,2,3,4,5,6,7,8,9,10);

We want to define an operation that stops when x > 5.

We define a general splitter:

public class CustomSpliterator<T> extends Spliterators.AbstractSpliterator<T>  {

    private Spliterator<T> splitr;
    private Predicate<T> predicate;
    private volatile boolean isMatched = true;

    public CustomSpliterator(Spliterator<T> splitr,Predicate<T> predicate) {
        super(splitr.estimateSize(),0);
        this.splitr = splitr;
        this.predicate = predicate;
    }

    @Override
    public synchronized boolean tryAdvance(Consumer<? super T> consumer) {
        boolean hadNext = splitr.tryAdvance(elem -> {
            if (predicate.test(elem) && isMatched) {
                consumer.accept(elem);
            } else {
                isMatched = false;
            }
        });
        return hadNext && isMatched;
    }
}

In the above class, predicate is the judgment condition we will pass in. We override tryadvance by Test (elem) adds judgment conditions to return false when the conditions are not met

See how to use:

@Slf4j
public class CustomSpliteratorUsage {

    public static <T> Stream<T> takeWhile(Stream<T> stream,Predicate<T> predicate) {
        CustomSpliterator<T> customSpliterator = new CustomSpliterator<>(stream.spliterator(),predicate);
        return StreamSupport.stream(customSpliterator,false);
    }

    public static void main(String[] args) {
        Stream<Integer> ints = Stream.of(1,10);
        List<Integer> result =
          takeWhile(ints,x -> x < 5 )
                        .collect(Collectors.toList());
        log.info(result.toString());
    }
}

We define a takeWhile method to receive stream and predicate conditions.

It will continue only when the predicate condition is met. Let's see the output results:

[main] INFO com.flydean.CustomSpliteratorUsage - [1,4]

Custom foreach method

In addition to using the splitter, we can also customize the foreach method to use our own traversal logic:

public class CustomForEach {

    public static class Breaker {
        private volatile boolean shouldBreak = false;

        public void stop() {
            shouldBreak = true;
        }

        boolean get() {
            return shouldBreak;
        }
    }

    public static <T> void forEach(Stream<T> stream,BiConsumer<T,Breaker> consumer) {
        Spliterator<T> spliterator = stream.spliterator();
        boolean hadNext = true;
        Breaker breaker = new Breaker();

        while (hadNext && !breaker.get()) {
            hadNext = spliterator.tryAdvance(elem -> {
                consumer.accept(elem,breaker);
            });
        }
    }
}

In the above example, we introduced an external variable in foreach to determine whether to enter the splitter Tryadvance method.

See how to use:

@Slf4j
public class CustomForEachUsage {

    public static void main(String[] args) {
        Stream<Integer> ints = Stream.of(1,10);
        List<Integer> result = new ArrayList<>();
        CustomForEach.forEach(ints,(elem,breaker) -> {
            if (elem >= 5 ) {
                breaker.stop();
            } else {
                result.add(elem);
            }
        });
        log.info(result.toString());
    }
}

Above, we use the new foreach method and reset the judgment flag through the judgment conditions, so as to achieve the purpose of break stream.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>