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 ...
- alembic 数据库管理
alembic简介 Alembic是SQLAlchemy作者编写的Python数据库迁移工具 安装 pip install alembic alembic 操作流程 初始化 alembic init ...
- [翻译] BBCyclingLabel
BBCyclingLabel BBCyclingLabel is just like a UILabel but allows you to perform custom animations whe ...
- 执行系统命令,subprocess使用说明
os.system('ls -l') #只执行命令,不能将结果赋予变量 os.system('mkdir test') #创建test目录 files = os.popen('ls -l').rea ...
- dADas
Linux(Centos)之安装Nginx及注意事项 - Kencery - 博客园 怪才(Kencery) 菜鸟的里程中只有奋斗,别无其他 博客园 首页 新随笔 联系 订阅 管理 Linux ...
- cmd pyhton
在cmd中运行python解释器: 1.同时执行多条指令,可在多条指令中间使用 & 连接 >>> print('123') &print('223') 123 223
- 沉淀再出发:ElasticSearch的中文分词器ik
沉淀再出发:ElasticSearch的中文分词器ik 一.前言 为什么要在elasticsearch中要使用ik这样的中文分词呢,那是因为es提供的分词是英文分词,对于中文的分词就做的非常不好了 ...
- 沉淀,再出发:jQuery的初步了解和入门
沉淀,再出发:jQuery的初步了解和入门 一.前言 对于后端开发者来说,是不是真的不需要了解前端的开发经过和相关技术,从我个人的角度来说,我觉得如果不了解或者接触很少,极有可能造成开发的时候 ...
- 016.2 String
内容:String方法+练习 #######################################比较方法:equals()字符串长度:int length()字符的位置:int index ...
- jQueryeasyUI+Hibernate+struts2实现商城后台管理之添加操作时的unique验证
1. 在admin.js中添加扩展验证的操作checkName var checkUrl = "./hytc/AdminAction_check.action";