怎么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

欢迎关注我的公众号:程序那些事,更多精彩等着您!

更多内容请访问 www.flydean.com

怎么break java8 stream的foreach的更多相关文章

  1. java8 Stream的实现原理 (从零开始实现一个stream流)

    1.Stream 流的介绍 1.1 java8 stream介绍 java8新增了stream流的特性,能够让用户以函数式的方式.更为简单的操纵集合等数据结构,并实现了用户无感知的并行计算. 1.2  ...

  2. 如何用Java8 Stream API找到心仪的女朋友

    传统的的Java 集合操作是有些啰嗦的,当我们需要对结合元素进行过滤,排序等操作的时候,通常需要写好几行代码以及定义临时变量. 而Java8 Stream API 可以极大简化这一操作,代码行数少,且 ...

  3. java List递归排序,传统方式和java8 Stream优化递归,无序的列表按照父级关系进行排序(两种排序类型)

    当有一个List列表是无序的,List中的数据有parentid进行关联,通过java排序成两种排序类型: 所用的测试列表最顶级无parentid,若为特殊值,修改下判断方法即可. 第一种排序:按照树 ...

  4. 简洁又快速地处理集合——Java8 Stream(下)

    上一篇文章我讲解 Stream 流的基本原理,以及它与集合的区别关系,讲了那么多抽象的,本篇文章我们开始实战,讲解流的各个方法以及各种操作 没有看过上篇文章的可以先点击进去学习一下 简洁又快速地处理集 ...

  5. 简洁又快速地处理集合——Java8 Stream(上)

    Java 8 发布至今也已经好几年过去,如今 Java 也已经向 11 迈去,但是 Java 8 作出的改变可以说是革命性的,影响足够深远,学习 Java 8 应该是 Java 开发者的必修课. 今天 ...

  6. java8 Stream使用总结

    [前言] java8新特性 java8 函数接口 java8 Optional使用总结 Java 8 时间日期使用 java8 lambda表达式 1.流的介绍 Java8 中的 Stream 是对集 ...

  7. Java8 Stream新特性详解及实战

    Java8 Stream新特性详解及实战 背景介绍 在阅读Spring Boot源代码时,发现Java 8的新特性已经被广泛使用,如果再不学习Java8的新特性并灵活应用,你可能真的要out了.为此, ...

  8. 【转】Java8 Stream 流详解

      当我第一次阅读 Java8 中的 Stream API 时,说实话,我非常困惑,因为它的名字听起来与 Java I0 框架中的 InputStream 和 OutputStream 非常类似.但是 ...

  9. 何用Java8 Stream API进行数据抽取与收集

    上一篇中我们通过一个实例看到了Java8 Stream API 相较于传统的的Java 集合操作的简洁与优势,本篇我们依然借助于一个实际的例子来看看Java8 Stream API 如何抽取及收集数据 ...

随机推荐

  1. [教程]KALI LINUX 2.0 2019 更新国内源

    2019年最新版本KALI 为 KALI 2019.1 下载地址:https://www.kali.org/downloads/ 有的新入门的朋友可能会问,为什么每次都无法手动更新 例如:Update ...

  2. what the fuck!(二分查找 / 暴力模拟)

    what the fuck! Description 现在有一家公司有nnn个员工(nnn为奇数),他们的工资发放是基本工资+提成,现在这家公司计划再招一批人.要写一篇招聘启事,但是对于这个招聘启事中 ...

  3. linux下使用笔记本的相关设置

    目录 无线连接 Wi-Fi 蓝牙 触摸板 电源管理 电源管理工具 电源相关行为的响应动作 按键和盖子的响应动作 电池低电量的响应动作 处理器调整 调频工具 关闭睿频 intel_pstate 休眠配置 ...

  4. 发现了合自己胃口的公众号,但文章太多翻来翻去真麻烦,还好我学了 Python

    现在我们大多数人都会或多或少的关注几个公众号,如果发现一个比较合自己胃口的号 对公众号中的文章一定是每篇必读的. 有时候我们关注到宝藏型公众号时发现其历史文章已经好几百甚至上千篇了,而作者又只对其中自 ...

  5. Mysql千万级记录表分表策略

    目前,比较流行的分表为2倍扩容. 表A(id, name, age, sex) 基于自增id分表, 通过触发器先同步A到B, 程序通过mod 2操作数据,然后drop掉触发器,在 删除两个A表的偶数i ...

  6. 10-jmeter 测试soap协议v1.2版本请求

    1.因为jmeter安装了第三方插件jmeter-plugins-manager.jar之后(具体安装看之前文章),此时就可简单直接测试soap协议1.2版本的请求了 2. 3.进行运行线程就可实现了 ...

  7. tf.nn.sigmoid_cross_entropy_with_logits 分类

    tf.nn.sigmoid_cross_entropy_with_logits(_sentinel=None,,labels=None,logits=None,name=None) logits和la ...

  8. JNDI数据源的配置及使用 (2010-11-21 21:16:43)转载▼

    JNDI数据源的配置及使用 (2010-11-21 21:16:43)转载▼ 标签: 杂谈 分类: 数据库 数据源的作用 JDBC操作的步骤: 1. 加载驱动程序 2. 连接数据库 3. 操作数据库 ...

  9. BAT脚本编写要点_特殊字符

    BAT脚本编写要点(1)_特殊字符 分类: 其他 2011-03-20 00:58 5621人阅读 评论(0) 收藏 举报 脚本cdatecmdtreesystem 1. 点 与echo连用,作用是换 ...

  10. SpringCloud-服务注册中心「Eureka」的介绍与使用

    Eureka 两大组件