【Java8新特性】面试官问我:Java8中创建Stream流有哪几种方式?
写在前面
先说点题外话:不少读者工作几年后,仍然在使用Java7之前版本的方法,对于Java8版本的新特性,甚至是Java7的新特性几乎没有接触过。真心想对这些读者说:你真的需要了解下Java8甚至以后版本的新特性了。
今天,一名读者出去面试,面试官问他:说说Java8中创建Stream流有哪几种方式?他竟然没回答上来!!
Stream概述
Java8中有两大最为重要的改变。第一个是 Lambda 表达式;另外一个则是 Stream API(java.util.stream.*)。
Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。
何为Stream?
流(Stream) 到底是什么呢?
可以这么理解流:流就是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
“集合讲的是数据,流讲的是计算! ”
注意:
①Stream 自己不会存储元素。
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
Stream操作步骤
1.创建 Stream
一个数据源(如: 集合、数组), 获取一个流。
2.中间操作
一个中间操作链,对数据源的数据进行处理。
3.终止操作(终端操作)
一个终止操作,执行中间操作链,并产生结果 。

如何创建Stream流?
这里,创建测试类TestStreamAPI1,所有的操作都是在TestStreamAPI1类中完成的。
(1)通过Collection系列集合提供的stream()方法或者parallelStream()方法来创建Stream。
在Java8中,Collection 接口被扩展,提供了两个获取流的默认方法,如下所示。
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
其中,stream()方法返回一个顺序流,parallelStream()方法返回一个并行流。
我们可以使用如下代码方式来创建顺序流和并行流。
List<String> list = new ArrayList<>();
list.stream();
list.parallelStream();
(2)通过Arrays中的静态方法stream()获取数组流。
Java8 中的 Arrays类的静态方法 stream() 可以获取数组流 ,如下所示。
public static <T> Stream<T> stream(T[] array) {
return stream(array, 0, array.length);
}
上述代码的的作用为:传入一个泛型数组,返回这个泛型的Stream流。
除此之外,在Arrays类中还提供了stream()方法的如下重载形式。
public static <T> Stream<T> stream(T[] array) {
return stream(array, 0, array.length);
}
public static <T> Stream<T> stream(T[] array, int startInclusive, int endExclusive) {
return StreamSupport.stream(spliterator(array, startInclusive, endExclusive), false);
}
public static IntStream stream(int[] array) {
return stream(array, 0, array.length);
}
public static IntStream stream(int[] array, int startInclusive, int endExclusive) {
return StreamSupport.intStream(spliterator(array, startInclusive, endExclusive), false);
}
public static LongStream stream(long[] array) {
return stream(array, 0, array.length);
}
public static LongStream stream(long[] array, int startInclusive, int endExclusive) {
return StreamSupport.longStream(spliterator(array, startInclusive, endExclusive), false);
}
public static DoubleStream stream(double[] array) {
return stream(array, 0, array.length);
}
public static DoubleStream stream(double[] array, int startInclusive, int endExclusive) {
return StreamSupport.doubleStream(spliterator(array, startInclusive, endExclusive), false);
}
基本上能够满足基本将基本类型的数组转化为Stream流的操作。
我们可以通过下面的代码示例来使用Arrays类的stream()方法来创建Stream流。
Integer[] nums = new Integer[]{1,2,3,4,5,6,7,8,9};
Stream<Integer> numStream = Arrays.stream(nums);
(3)通过Stream类的静态方法of()获取数组流。
可以使用静态方法 Stream.of(), 通过显示值创建一个流。它可以接收任意数量的参数。
我们先来看看Stream的of()方法,如下所示。
public static<T> Stream<T> of(T t) {
return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
}
@SafeVarargs
@SuppressWarnings("varargs")
public static<T> Stream<T> of(T... values) {
return Arrays.stream(values);
}
可以看到,在Stream类中,提供了两个of()方法,一个只需要传入一个泛型参数,一个需要传入一个可变泛型参数。
我们可以使用下面的代码示例来使用of方法创建一个Stream流。
Stream<String> strStream = Stream.of("a", "b", "c");
(4)创建无限流
可以使用静态方法 Stream.iterate() 和Stream.generate(), 创建无限流。
先来看看Stream类中iterate()方法和generate()方法的源码,如下所示。
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
Objects.requireNonNull(f);
final Iterator<T> iterator = new Iterator<T>() {
@SuppressWarnings("unchecked")
T t = (T) Streams.NONE;
@Override
public boolean hasNext() {
return true;
}
@Override
public T next() {
return t = (t == Streams.NONE) ? seed : f.apply(t);
}
};
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
iterator,
Spliterator.ORDERED | Spliterator.IMMUTABLE), false);
}
public static<T> Stream<T> generate(Supplier<T> s) {
Objects.requireNonNull(s);
return StreamSupport.stream(
new StreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE, s), false);
}
通过源码可以看出,iterate()方法主要是使用“迭代”的方式生成无限流,而generate()方法主要是使用“生成”的方式生成无限流。我们可以使用下面的代码示例来使用这两个方法生成Stream流。
- 迭代
Stream<Integer> intStream = Stream.iterate(0, (x) -> x + 2);
intStream.forEach(System.out::println);
运行上述代码,会在终端一直输出偶数,这种操作会一直持续下去。如果我们只需要输出10个偶数,该如何操作呢?其实也很简单,使用Stream对象的limit方法进行限制就可以了,如下所示。
Stream<Integer> intStream = Stream.iterate(0, (x) -> x + 2);
intStream.limit(10).forEach(System.out::println);
- 生成
Stream.generate(() -> Math.random()).forEach(System.out::println);
上述代码同样会一直输出随机数,如果我们只需要输出5个随机数,则只需要使用limit()方法进行限制即可。
Stream.generate(() -> Math.random()).limit(5).forEach(System.out::println);
(5)创建空流
在Stream类中提供了一个empty()方法,如下所示。
public static<T> Stream<T> empty() {
return StreamSupport.stream(Spliterators.<T>emptySpliterator(), false);
}
我们可以使用Stream类的empty()方法来创建一个空Stream流,如下所示。
Stream<String> empty = Stream.empty();
写在最后
如果觉得文章对你有点帮助,请微信搜索并关注「 冰河技术 」微信公众号,跟冰河学习Java8新特性。
最后,附上Java8新特性核心知识图,祝大家在学习Java8新特性时少走弯路。

【Java8新特性】面试官问我:Java8中创建Stream流有哪几种方式?的更多相关文章
- 当阿里面试官问我:Java创建线程有几种方式?我就知道问题没那么简单
这是最新的大厂面试系列,还原真实场景,提炼出知识点分享给大家. 点赞再看,养成习惯~ 微信搜索[武哥聊编程],关注这个 Java 菜鸟. 昨天有个小伙伴去阿里面试实习生岗位,面试官问他了一个老生常谈的 ...
- 面试官问:Go 中的参数传递是值传递还是引用传递?
一个程序中,变量分为变量名和变量内容,变量内容的存储一般会被分配到堆和栈上.而在 Go 语言中有两种传递变量的方式值传递和引用传递.其中值传递会直接将变量内容附在变量名上传递,而引用传递会将变量内容的 ...
- 腾讯面试官问我Java中boolean类型占用多少个字节?我说一个,面试官让我回家等通知
本文首发于微信公众号:程序员乔戈里 什么是boolean类型,根据官方文档的描述: boolean: The boolean data type has only two possible value ...
- 面试官问我“Java中的锁有哪些?以及区别”,我跪了
在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容如下: 公平锁/非公平锁 可重入锁 独享锁/共享锁 互斥锁/读写锁 乐观锁/悲观锁 分段锁 偏向锁/轻量级 ...
- 面试官问:Mybatis中的TypeHandler你用过吗?
持续原创输出,点击上方蓝字关注我吧 目录 前言 环境配置 什么是TypeHandler? 如何自定义? 如何将其添加到Mybatis中? XML文件中如何指定TypeHandler? 源码中如何执行T ...
- 【Java8新特性】Stream API有哪些中间操作?看完你也可以吊打面试官!!
写在前面 在上一篇<[Java8新特性]面试官问我:Java8中创建Stream流有哪几种方式?>中,一名读者去面试被面试官暴虐!归根结底,那哥儿们还是对Java8的新特性不是很了解呀!那 ...
- 【Java8新特性】面试官:谈谈Java8中的Stream API有哪些终止操作?
写在前面 如果你出去面试,面试官问了你关于Java8 Stream API的一些问题,比如:Java8中创建Stream流有哪几种方式?(可以参见:<[Java8新特性]面试官问我:Java8中 ...
- 【Java8新特性】你知道Java8为什么要引入Lambda表达式吗?
写在前面 这是一道真实的面试题,一个读者朋友出去面试,面试官竟然问他这样一个问题:你说说Java8中为什么引入Lambda表达式?引入Lambda表达式后有哪些好处呢?还好这个朋友对Java8早有准备 ...
- 这可能是史上最好的 Java8 新特性 Stream 流教程
本文翻译自 https://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/ 作者: @Winterbe 欢迎关注个人微信公众 ...
随机推荐
- vs code中Vue代码格式化的问题
个人网站 https://iiter.cn 程序员导航站 开业啦,欢迎各位观众姥爷赏脸参观,如有意见或建议希望能够不吝赐教! VSCode自从更新之后,vue文件的html代码格式化就失效了,而且vu ...
- du命令、df命令、磁盘分区
df:汇报文件系统的磁盘使用空间[root@localhost ~]# df文件系统 1K-块 已用 可用 已用% 挂载点/dev/sda3 29140072 1022920 28117152 4% ...
- codeforce 1311 D. Three Integers
In one move, you can add +1 or −1 to any of these integers (i.e. increase or decrease any number by ...
- css属性、样式、边框、选择器
CSS 层叠样式表 (Cascading Style Sheets,缩写为 CSS),是一种 样式表 语言, 用来描述 HTML或 XML(包括如 SVG.MathML.XHTML 之类的 XML 分 ...
- 程序猿使用Python的tkinter库进行GUI编程肯定要会的事件处理
事件类型用户通过鼠标.键盘.游戏控制设备在与图形界面交互时,就会触发事件.tkinter事件通常采用了将事件名称放置于尖括号内的字符串表示,尖括号中的内容我们称之为事件类型.事件类型有其通用的定义方式 ...
- 使用npm发布插件
使用npm发布插件 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! 简介 npm是一个全球性的包管理工具,上面有着许许多多的前端 ...
- 前缀和(P2697 宝石串)
前言 每次做出来什么本来做不出的题目,就忍不住记录一下.不过大多时候隔几天来看,就发现,啊,我当时只是做了一道这么弱智的题目呀,哈哈.前缀和确实不算太难.. 传送门 题目大意: 给你一个字符串只含G和 ...
- .NET Core接入ElasticSearch 7.5
写在前面 最近一段时间,团队在升级ElasticSearch(以下简称ES),从ES 2.2升级到ES 7.5.也是这段时间,我从零开始,逐步的了解了ES,中间也踩了不少坑,所以特地梳理和总结一下相关 ...
- fakebook
0x01 查看robots.txt 发现user.php.bak文件 得到源码 <?php class UserInfo { public $name = ""; publi ...
- react-grid-layout实现拖拽,网格布局
借鉴地址:https://www.jianshu.com/p/b48858eee3a7 安装 react-grid-layout npm install react-grid-layout impor ...