JAVA8 Stream流
2020-06-02 16:06:37来源:博客园 阅读 ()
JAVA8 Stream流
简介
Stream
是一个 Collection
的增强工具,可以对集合进行各种操作,而且可以很方便的写出并发程序,学习之前需要了解一些函数,可以看 JAVA8 Lambda表达式。常见的获取方式就是 Collection.stream()
。
操作类型
操作类型分为三种
Intermediate
(中间操作):可以多次使用,因为返回一个Stream
。比如map(mapToInt, flatMap)
、filter
、sorted
、limit
、skip
。Terminal
(结束操作):使用后就会结束。比如forEach
、sort
、collect
、min
、count
、findFirst
、anyMatch
。
中间操作都是惰性的,也就是延迟的,所以会产生副作用,关于副作用会在之后的章节详细说明。
创建
Stream
的类型有三种 IntStream
,DoubleStream
和 LongStream
,当然也可以使用 Stream<T>
。
除了直接创建,还能通过 Collection
接口的 stream()
和 parallelStream()
创建,其中 parallelStream()
创建的流是并发、线程不安全且操作无序的,虽然它是并发的,但仍有可能在某些操作下变回串行的,例如 forEachOrdered
,此外还需要保证数据源是线程安全的。
下面的代码展示了流的创建,第二行代码是取流中前三个元素在控制台输出,如果开启最后一行注释将会出现 java.lang.IllegalStateException
的异常,详细错误信息为 stream has already been operated upon or closed
,所以创建的 Stream
仅能使用一次。
IntStream intStream = IntStream.of(1, 2, 3, 4);
intStream.limit(3).forEach(System.out::println);
//intStream.limit(1).forEach(System.out::println);
使用
JAVA8 中 Stream
接口中的操作有 filter
、map
、mapToInt
、mapToLong
、mapToDouble
、flatMap
、flatMapToInt
、flatMapToLong
、flatMapToDouble
、distinct
、sorted
、peek
、limit
、skip
、forEach
、forEachOrdered
、toArray
、reduce
、collect
、min
、max
、count
、anyMatch
、allMatch
、noneMatch
、findFirst
、findAny
,方法很多,没见过的看注释、参数和返回值就懂了。
示例使用 List
接口 的 stream
方法创建 Stream
,下面是示例所需要的数据。
//Get、Set、构造方法浪费空间,不粘贴了
public class Person {
//id
private Integer id;
//名字
private String name;
//年龄
private Integer age;
//组织
private String organization;
}
//数据初始化
List<Person> personList = new ArrayList<>();
personList.add(new Person(1, "灰原哀", 7, "帝丹小学"));
personList.add(new Person(2, "江户川柯南", 7, "帝丹小学"));
personList.add(new Person(3, "宫野明美", 24, "黑衣组织"));
personList.add(new Person(4, "赤井秀一", 27, "FBI"));
personList.add(new Person(5, "贝尔摩德", 29, "黑衣组织"));
下面是对 Stream
操作的两个个简单示例。
第一个将 personList
中 前 4 个、年龄为 7 的人提取出来,以组织和姓名为 key
和 value
组装成一个新的 Map
,其中 Collectors.toMap
方法最后一个参数用于解决 key
冲突。
第二个获取 personList
中名字为安室透的第一个人。
Map<String, String> map = personList.stream().limit(4) //中间操作
.filter(person -> Objects.equals(person.getAge(), 7)) //中间操作
.collect(Collectors.toMap( // Collectors 类是随 Stream 一起引入的,即方便又好看,作用之一是收集元素到集合
Person::getOrganization, // map 的 key
Person::getName, // map 的 value
(old, now) -> old)); // 发生冲突的解决办法
Optional<Person> optional = personList.stream()
.filter(person->Objects.equals(person.getName(), "安室透")) //中间操作
.findFirst();
第二个方法返回值类型是 Optional<Person>
,Optional
是 JAVA8 中引入的一个容器,可以使用 get()
获取容器中的值,但 optional
中并没有值,所以会抛出 java.util.NoSuchElementException
,为了解决这个问题可以使用 orElse()
,当容器中值为空时返回设定的默认值,除了 orElse
还有 orElseGet
和 orElseThrow
。比如下面的这段代码返回了叫安室透的人。
// optional 在上一段代码中产生的对象
Person person = optional.orElse(new Person(7, "安室透", 29, "日本公安"));
副作用
对流的中间操作会产生副作用,结果是抛异常和数据的错误,它的来源有“干扰”和“有状态的 Lambda”。
- “干扰”就是在中间操作时修改了流的数据源。比如在
forEach(Consumer<? super T> action)
中应该是消费数据,却给数据源添加了一个数据,结果是抛出了java.util.ConcurrentModificationException
异常。 - “有状态的 Lambda”,当后面操作产生的结果会被前面的操作影响时,前面操作的
Lambda
就被称作是有状态的。比如 有状态的 Lambda 的例子,例子中使用parallelStream()
并发添加数据到parallelStorage
中,结果就是parallelStorage
中的数据顺序不可预测,因此称e -> { parallelStorage.add(e); return e; }
是有状态的Lambda
。
总结
本文没有深入介绍它的概念,只是简单介绍了 Stream
的使用和 Optional
容器,对于了解应该够了。
参考资料
为什么需要 Stream
Stream 副作用
Java 8 Stream 的终极技巧——Collectors 功能与操作方法详解
Java8(3)Stream类的collect方法详解
原文链接:https://www.cnblogs.com/hligy/p/13033718.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- 学习Java 8 Stream Api (4) - Stream 终端操作之 collect 2020-06-11
- Spring WebFlux 学习笔记 - (一) 前传:学习Java 8 Stream Ap 2020-06-11
- Java--Stream流详解 2020-06-10
- java8 stream的分组功能,具体时候是真的好用 2020-06-10
- XStream学习手册 2020-06-04
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash