怎么break java8 stream的foreach

简介: 怎么break java8 stream的foreach

目录



怎么break java8 stream的foreach


简介


我们通常需要在java stream中遍历处理里面的数据,其中foreach是最最常用的方法。


但是有时候我们并不想处理完所有的数据,或者有时候Stream可能非常的长,或者根本就是无限的。


一种方法是先filter出我们需要处理的数据,然后再foreach遍历。


那么我们如何直接break这个stream呢?今天本文重点讲解一下这个问题。


使用Spliterator


上篇文章我们在讲Spliterator的时候提到了,在tryAdvance方法中,如果返回false,则Spliterator将会停止处理后续的元素。


通过这个思路,我们可以创建自定义Spliterator。


假如我们有这样一个stream:


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


我们想定义一个操作,当x > 5的时候就停止。


我们定义一个通用的Spliterator:


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


在上面的类中,predicate是我们将要传入的判断条件,我们重写了tryAdvance,通过将predicate.test(elem)加入判断条件,从而当条件不满足的时候返回false.


看下怎么使用:


@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, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        List<Integer> result =
          takeWhile(ints, x -> x < 5 )
                        .collect(Collectors.toList());
        log.info(result.toString());
    }
}


我们定义了一个takeWhile方法,接收Stream和predicate条件。


只有当predicate条件满足的时候才会继续,我们看下输出的结果:


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


自定义forEach方法


除了使用Spliterator,我们还可以自定义forEach方法来使用自己的遍历逻辑:


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


上面的例子中,我们在forEach中引入了一个外部变量,通过判断这个外部变量来决定是否进入spliterator.tryAdvance方法。


看下怎么使用:


@Slf4j
public class CustomForEachUsage {
    public static void main(String[] args) {
        Stream<Integer> ints = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        List<Integer> result = new ArrayList<>();
        CustomForEach.forEach(ints, (elem, breaker) -> {
            if (elem >= 5 ) {
                breaker.stop();
            } else {
                result.add(elem);
            }
        });
        log.info(result.toString());
    }
}


上面我们用新的forEach方法,并通过判断条件来重置判断flag,从而达到break stream的目的。


总结


本文通过两个具体的例子讲解了如何break一个stream,希望大家能够喜欢。


本文的例子https://github.com/ddean2009/learn-java-streams/tree/master/break-stream-foreach

相关文章
|
7月前
|
Java API 数据处理
Java新特性:使用Stream API重构你的数据处理
Java新特性:使用Stream API重构你的数据处理
|
7月前
|
Java 大数据 API
Java Stream API:现代集合处理与函数式编程
Java Stream API:现代集合处理与函数式编程
360 100
|
7月前
|
Java API 数据处理
Java Stream API:现代集合处理新方式
Java Stream API:现代集合处理新方式
366 101
|
7月前
|
并行计算 Java 大数据
Java Stream API:现代数据处理之道
Java Stream API:现代数据处理之道
395 101
|
8月前
|
存储 Java API
Java Stream API:现代数据处理之道
Java Stream API:现代数据处理之道
436 188
|
8月前
|
存储 Java API
Java Stream API:现代数据处理之道
Java Stream API:现代数据处理之道
344 92
|
9月前
|
Oracle Java 关系型数据库
掌握Java Stream API:高效集合处理的利器
掌握Java Stream API:高效集合处理的利器
451 80
|
9月前
|
安全 Java API
Java 8 Stream API:高效集合处理的利器
Java 8 Stream API:高效集合处理的利器
360 83
|
6月前
|
Java Unix Go
【Java】(8)Stream流、文件File相关操作,IO的含义与运用
Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。!但本节讲述最基本的和流与 I/O 相关的功能。我们将通过一个个例子来学习这些功能。
269 1
|
7月前
|
存储 数据可视化 Java
Java Stream API 的强大功能
Java Stream API 是 Java 8 引入的重要特性,它改变了集合数据的处理方式。通过声明式语法,开发者可以更简洁地进行过滤、映射、聚合等操作。Stream API 支持惰性求值和并行处理,提升了代码效率和可读性,是现代 Java 开发不可或缺的工具。
146 0
Java Stream API 的强大功能
下一篇
开通oss服务