jdk8新特性-stream
一、什么是流stream
1.可理解为高级版本的 Iterator
不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的。
2.单向,不可往复
数据只能遍历一次,遍历过一次后即用尽了,就好比流水从面前流过,一去不复返。
3.可并行化操作
迭代器:只能命令式地、串行化操作。当使用串行方式去遍历时,每个 item 读完后再读下一个 item。和迭代器不同,stream使用并行去遍历时,数据会被分成多个段,其中每一个都在不同的线程中处理,然后将结果一起输出。
4.数据源本身可以是无限的
二、流的构成
1.构成的三个步骤
a.获取一个数据源(source)
b.数据转换
c.执行操作获取想要的结果。<每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象(可以有多次转换),这就允许对其操作可以像链条一样排列,变成一个管道>。如下图所示:
eg:Student<id, name> List<Student> students = Lists.newArrayList(new Student(1, "学生1"), new Student(2, "学生2"), new Student(3, "学生3")); --- Source Stream<Student> studentStream = students.stream(); --- Stream Stream<Long> idStream = studentStream.map(student -> student.getId); --- Transforming List<Long> ids = idStream.collect(Collectors.toList()); --- Operations

三、流的常见3种方法
- Collection.stream()
- Collection.parallelStream()
- Arrays.stream(T array) or Stream.of()
- Stream.generate(Supplier<T> s)。<创建无限流,不常用>
// 1. Individual values
Stream stream = Stream.of("a", "b", "c");
// 2. Arrays
String [] strArray = new String[] {"a", "b", "c"};
stream = Stream.of(strArray);
stream = Arrays.stream(strArray);
// 3. Collections
List<String> list = Arrays.asList(strArray);
stream = list.stream();
四、基本类型的流的构造
三种对应的包装类型 Stream。
IntStream、LongStream、DoubleStream
或者
Stream<Integer>、Stream<Long>、Stream<Double>
eg:
IntStream.of(new int[]{1, 2, 3}).forEach(System.out::println);
IntStream.range(1, 3).forEach(System.out::println);
IntStream.rangeClosed(1, 3).forEach(System.out::println);
五、流转换为其它数据结构
// 1. Array
String[] strArray1 = stream.toArray(String[]::new);
// 2. Collection
List<String> list1 = stream.collect(Collectors.toList());
List<String> list2 = stream.collect(Collectors.toCollection(ArrayList::new));
Set set1 = stream.collect(Collectors.toSet());
Stack stack1 = stream.collect(Collectors.toCollection(Stack::new));
// 3. String
String str = stream.collect(Collectors.joining()).toString();
六、流的操作
- Intermediate:
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
- Terminal:
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
- Short-circuiting:
anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit
七、典型用法
1.map:
map 生成的是个 1:1 映射,每个输入元素,都按照规则转换成为另外一个元素。作用:对流中的每一个元素进行操作。
1. 转换大写
List<String> output = wordList.stream().
map(String::toUpperCase).
collect(Collectors.toList());
说明:这段代码把每个单词转换为大写。
2. 平方数
List<Integer> nums = Arrays.asList(1, 2, 3, 4);
List<Integer> squareNums = nums.stream().
map(n -> n * n).
collect(Collectors.toList());
2.filter:
注意:这里要注意的是“过滤出”,而不是“过滤”,这是两个不同的意思!
1.留下偶数
Integer[] sixNums = {1, 2, 3, 4, 5, 6};
Integer[] evens = Stream.of(sixNums).filter(n -> n%2 == 0).toArray(Integer[]::new);
注意:stream也是可以foreach的,没必要一定要转化成集合再foreach
3.forEach
作用:对stream中的每一个元素做聚合操作。
List<Integer> numbers = Lists.newArrayList(1, 2, 3, 4);
System.out.println(numbers.stream().mapToInt(Integer::intValue).sum()); --输出10
4.reduce
作用:对stream中的每一个元素做聚合操作。
Stream<Integer> reduceStream = Stream.of(1,2,3,4,5);
Optional<Integer> sumOption = reduceStream.reduce((x,y)->x+y);//计算1+2+3+4+5,即对元素中的元素进行聚合计算,而map是对元素中的每一个元素分别计算(注意:如果stream为null的话,就会产生无效的结果,需要使用Optional接收)
//Optional<Integer> sumOption = reduceStream.reduce(Integer::sum);//计算1+2+3+4+5,即对元素中的元素进行聚合计算,而map是对元素中的每一个元素分别计算
Integer result = reduceStream.reduce(0, Integer::sum);//0为标识值,即计算:0+1+2+。。+5,如果整个stream为null,就返回标识值。
System.out.println(result);
注意:以上是reduce的简单形式,即内联函数是(T,T)->T,即返回值和参数类型是一样的,返回值和参数类型不同的场景需要自己编写函数(用的较少)
5、Optional两种用法:
ifPresent(xxx):存在的就执行xxx,不存在就什么都不执行
orElse(xxx):存在就返回存在的值,不存在就返回xxx(可以理解为是默认值)
Stream<String> optionalStream = Stream.of("java","python","basic");
Optional<String> optionValue = optionalStream.filter(str->str.startsWith("p")).findFirst();
optionValue.ifPresent(str->System.out.println(str));//if optionalValue为true,即str存在,则输出str,当然也可以使用如下
String str = optionValue.orElse("xxx");//如果optionValue为false,即不存在以p开头的字符串时,使用"xxx"来替代
System.out.println(str);
5、limit skip contact1、limit(long size)作用:截取stream的前size个元素。
Stream<String> streamSelf = Stream.of("python","basic","php");
streamSelf.limit(2).forEach(System.out::println);//截取前两个
2、skip(long size)作用:跳过stream的钱size个元素
Stream<String> streamSelf = Stream.of("python","basic","php");
streamSelf.skip(2).forEach(System.out::println);//跳过前两个
3、contact(Stream<T>,Stream<T>)作用:拼接两个stream
Stream<String> streamSelf = Stream.of("python","basic","php");
Stream<String> streamSelf2 = Stream.of("python2","basic2","php2");
Stream.concat(streamSelf, streamSelf2).forEach(System.out::println);
6.聚合函数
count max min findFirst findAny anyMatch allMatch noneMatch
Stream<String> streamSelf = Stream.of("python","basic","php","b");
System.out.println(streamSelf.count());//计算流中的元素个数
Optional<String> largest = streamSelf.max(String::compareToIgnoreCase);//寻找最大值
if(largest.isPresent()){
System.out.println(largest.get());
}
说明:min函数也一样。注意:Optional的使用,上边的是最差的一种形式,见"六"。
Optional<String> firstMatch = streamSelf.filter(str->str.startsWith("b")).findFirst();//寻找第一个符合条件的元素
firstMatch.ifPresent(System.out::println);//这是Optional的第一种用法
Optional<String> anyMatch = streamSelf.parallel().filter(str->str.startsWith("b")).findAny();//返回集合中符合条件的任意一个元素,对于并行处理非常好(因为多个线程只要有一个线程找到了,整个计算就会结束)
if(anyMatch.isPresent()){
System.out.println(anyMatch.get());//这里的结果可能是b,有可能是basic
}
boolean isAnyMatch = streamSelf.parallel().anyMatch(str->str.startsWith("c"));//集合中是否有一个满足条件
System.out.println(isAnyMatch);
Stream<String> streamSelf3 = Stream.of("basic","b");
boolean isAllMatch = streamSelf3.parallel().allMatch(str->str.startsWith("b"));//集合中是否所有元素都满足条件
System.out.println(isAllMatch);
boolean isAllNotMatch = streamSelf.parallel().noneMatch(str->str.startsWith("p"));//集合中是否没有一个元素满足条件
System.out.println(isAllNotMatch);
注意:
optional的最佳用法:ifPresent()-->如果有就输出,如果没有,什么都不做
parallel():将stream转为并行流,并行流的使用一定要注意线程安全
七、java8 :: 用法 (JDK8 双冒号用法)
就是把方法当做参数传到stream内部,使stream的每个元素都传入到该方法里面执行一下。
尽量用::去代替->,培养良好的代码习惯。
双冒号运算就是Java中的[方法引用],[方法引用]的格式是:
类名::方法名
注意,没有()号。
案例:
使用前:
person -> person.getAge();
使用双冒号后:
Person::getAge 使用前:
new HashMap<>()
使用双冒号后:
HsahMap :: new 使用前:
MyTest.printValur(x));
使用双冒号后:
MyTest :: printValur
参考链接
Streams API详解
https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/
Stream API
https://www.cnblogs.com/sunny3096/p/7159521.html
jdk8新特性-stream的更多相关文章
- JDK8新特性---stream流
项目上用到了stream流,找篇blog,转载一下,介绍下Stream流的用法. 1 流概述 流是 JDK8 新增的成员,允许以声明性方式处理数据集合,可以把 Stream 流看作是遍历数据集合的一 ...
- jdk8 新特性stream().map()
1.大写字符串列表 1.1 简单的Java示例将Strings列表转换为大写 TestJava8.java package com.mkyong.java8; import java.util.Arr ...
- jdk8新特性Stream
Stream的方法描述与实例 1,filter 过滤 Person p1 = new Person(); p1.setName("P1"); p1.setAge(10); Per ...
- 【记录】【java】JDK8新特性Stream方式遍历集合
由于是以流方式,所以怎么操作也不改变原来的集合 1.普通遍历forEach List<String> list = new ArrayList(); list.add("a&qu ...
- JDK8新特性:使用stream、Comparator和Method Reference实现集合的优雅排序
大家对java接口Comparator和Comparable都不陌生,JDK8里面Comparable还和以前一样,没有什么改动:但是Comparator在之前基础上增加了很多static和defau ...
- JDK8新特性关于Stream流
在Java1.8之前还没有stream流式算法的时候,我们要是在一个放有多个User对象的list集合中,将每个User对象的主键ID取出,组合成一个新的集合,首先想到的肯定是遍历,如下: 1 2 3 ...
- JDK8新特性一览
转载自:http://blog.csdn.net/qiubabin/article/details/70256683 官方新特性说明地址 Jdk8新特性.png 下面对几个常用的特性做下重点说明. 一 ...
- 一次电话Java面试的问题总结(JDK8新特性、哈希冲突、HashMap原理、线程安全、Linux查询命令、Hadoop节点)
面试涉及问题含有: Java JDK8新特性 集合(哈希冲突.HashMap的原理.自动排序的集合TreeSet) 多线程安全问题 String和StringBuffer JVM 原理.运行流程.内部 ...
- JDK8 新特性
JDK8 新特性目录导航: Lambda 表达式 函数式接口 方法引用.构造器引用和数组引用 接口支持默认方法和静态方法 Stream API 增强类型推断 新的日期时间 API Optional 类 ...
随机推荐
- Android深入四大组件(五)Android8.0 根Activity启动过程(后篇)
前言 在几个月前我写了Android深入四大组件(一)应用程序启动过程(前篇)和Android深入四大组件(一)应用程序启动过程(后篇)这两篇文章,它们都是基于Android 7.0,当我开始阅读An ...
- MySQL两个表联合查询并按时间排序
有一张资金记录表,一张金币记录表,想以时间为单位,降序合并排列他们之间的信息,查询SQL如下: select * from (select * from t_money_logs union sele ...
- Python交互式编辑器ipthon notebook jupyter
简介 IPython NoteBook(jupyter)是一个综合的交互式编程环境,比原本python命令进入的交互式环境要强大很多,总之就是炫酷加实用,浏览器中写Python代码,访问源端linux ...
- PyCharm2018 安装及破解方法
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u012278016/article/details/81738676 目录 1>. 安装 2& ...
- 8.Bootstrap CSS编码规范
Bootstrap CSS编码规范 本节的介绍内容为 Bootstrap 中的 CSS 编码规范. 语法 用两个空格来代替制表符(tab) -- 这是唯一能保证在所有环境下获得一致展现的方法. 为选择 ...
- HTML 的 style 属性
style 属性用于改变 HTML 元素的样式. This text is in Verdana and red This text is in Times and blue This text is ...
- HBuilder:一个不错的web前端IDE(代码编辑器)
Web前端开发,2000之后基本就是三剑客的天下.到现在DW也是不错的HTMLcoder,如今的前端开发早已是JS的天下.但是DW对于JS方面就弱爆了.DW虽然支持JS语法高亮也支持JQuery Jq ...
- mysql在linux下的安装mysql-5.6.33
一.下载源码包 wget http://mirrors.sohu.com/mysql/MySQL-5.6/mysql-5.6.35-linux-glibc2.5-x86_64.tar.gz 二.解压源 ...
- Sybase常用时间日期函数
Sybase日期函数日期函数getdate()得到当前时间,可以设置得到各种时间格式.datepart(日期部分,日期)取指定时间的某一个部分,年月天时分秒.datediff(日期部分,日期1,日期2 ...
- 开闭原则(OCP)
开闭原则具有理想主义的色彩,它是面向对象设计的终极目标.因此,针对开闭原则的实现方法,一直都有面向对象设计的大师费尽心机,研究开闭原则的实现方式.后面要提到的里氏代换原则(LSP).依赖倒转原则(DI ...