一、Stream是什么?

  是数据通道,用于操作数据源(集合、数组等)所生成的元素序列。集合讲的是数据,流讲的是计算。

  注意:

    Stream不会存储元素。

    Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream。

    Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

  Stream操作的三个步骤:

    创建Stream:  一个数据源(如:集合、数组),获取一个流

    中间操作:一个中间操作链,对数据源的数据进行处理

    终止操作(终端操作):一个终止操作,执行中间操作链,并产生结果。

二、创建Stream

  1、Java8中的Collection接口被扩展,提供了两个获取流的方法。

    default Stream<E> stream() : 返回一个顺序流

    default Stream<E> parallelStream() : 返回一个并行流

//1. Collection 提供了两个方法  stream() 与 parallelStream()
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream(); //获取一个顺序流
Stream<String> parallelStream = list.parallelStream(); //获取一个并行流

  2、由数组创建流

    Java8中的Arrays的静态方法stream()可以获取数组流。

    static <T> Stream<T> stream(T[] array): 返回一个流

    重载形式,能够处理基本类型的数组:

    public static IntStream stream(int[] array)

    public static LongStream stream(long[] array)

    public static DoubleStream stream(double[] array)

//2. 通过 Arrays 中的 stream() 获取一个数组流
Integer[] nums = new Integer[10];
Stream<Integer> stream1 = Arrays.stream(nums);

  3、由值创建流

    可以使用静态方法Stream.of(),通过显示值创建一个流。它可以接收任意数量的参数。

    public static<T> Stream<T> of(T... values) : 返回一个流

Stream<Integer> stream2 = Stream.of(1,2,3,4,5,6);

  4、由函数创建无限流

    可以使用静态方法 Stream.iterate() 和Stream.generate(), 创建无限流。

    迭代:public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)

    生成:public static<T> Stream<T> generate(Supplier<T> s)  

//迭代
Stream<Integer> stream3 = Stream.iterate(0, (x) -> x + 2).limit(10);
stream3.forEach(System.out::println);
//生成
Stream<Double> stream4 = Stream.generate(Math::random).limit(2);
stream4.forEach(System.out::println);

三、Stream的中间操作

  多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“”惰性求值“”。

  1、筛选与切片

    

  ①filter

    //内部迭代:迭代操作 Stream API 内部完成
@Test
public void test2(){
//所有的中间操作不会做任何的处理
Stream<Employee> stream = emps.stream()
.filter((e) -> {
System.out.println("测试中间操作");
return e.getAge() <= 35;
}); //只有当做终止操作时,所有的中间操作会一次性的全部执行,称为“惰性求值”
stream.forEach(System.out::println);
}
    //外部迭代
@Test
public void test3(){
Iterator<Employee> it = emps.iterator(); while(it.hasNext()){
System.out.println(it.next());
}
}

  ②limit

    @Test
public void test4(){
emps.stream()
.filter((e) -> {
System.out.println("短路!"); // && ||
return e.getSalary() >= 5000;
}).limit(3)
.forEach(System.out::println);
}

  ③skip

    @Test
public void test5(){
emps.parallelStream()
.filter((e) -> e.getSalary() >= 5000)
.skip(2)
.forEach(System.out::println);
}

  ④distinct

    @Test
public void test6(){
emps.stream()
.distinct()
.forEach(System.out::println);
}

  2、映射

    ①映射

  

@Test
public void test1(){
Stream<String> str = emps.stream()
.map((e) -> e.getName()); System.out.println("-------------------------------------------"); List<String> strList = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee"); Stream<String> stream = strList.stream()
.map(String::toUpperCase); stream.forEach(System.out::println); Stream<Stream<Character>> stream2 = strList.stream()
.map(TestStreamAPI1::filterCharacter); stream2.forEach((sm) -> {
sm.forEach(System.out::println);
}); System.out.println("---------------------------------------------"); Stream<Character> stream3 = strList.stream()
.flatMap(TestStreamAPI1::filterCharacter); stream3.forEach(System.out::println);
}
    public static Stream<Character> filterCharacter(String str){
List<Character> list = new ArrayList<>(); for (Character ch : str.toCharArray()) {
list.add(ch);
} return list.stream();
}

  ②排序

   

    @Test
public void test2(){
emps.stream()
.map(Employee::getName)
.sorted()
.forEach(System.out::println); System.out.println("------------------------------------"); emps.stream()
.sorted((x, y) -> {
if(x.getAge() == y.getAge()){
return x.getName().compareTo(y.getName());
}else{
return Integer.compare(x.getAge(), y.getAge());
}
}).forEach(System.out::println);
}

  ③Stream终止操作

  终止操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、Integer、甚至是void。

  查找与匹配:

  

  

  match

    @Test
public void test1(){
boolean bl = emps.stream()
.allMatch((e) -> e.getStatus().equals(Status.BUSY)); System.out.println(bl); boolean bl1 = emps.stream()
.anyMatch((e) -> e.getStatus().equals(Status.BUSY)); System.out.println(bl1); boolean bl2 = emps.stream()
.noneMatch((e) -> e.getStatus().equals(Status.BUSY)); System.out.println(bl2);
}

  find

    @Test
public void test2(){
Optional<Employee> op = emps.stream()
.sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
.findFirst(); System.out.println(op.get()); System.out.println("--------------------------------"); Optional<Employee> op2 = emps.parallelStream()
.filter((e) -> e.getStatus().equals(Status.FREE))
.findAny(); System.out.println(op2.get());
}

  count、max、min

    @Test
public void test3(){
long count = emps.stream()
.filter((e) -> e.getStatus().equals(Status.FREE))
.count(); System.out.println(count); Optional<Double> op = emps.stream()
.map(Employee::getSalary)
.max(Double::compare); System.out.println(op.get()); Optional<Employee> op2 = emps.stream()
.min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())); System.out.println(op2.get());
}

进行了终止操作后不能再次使用

    //注意:流进行了终止操作后,不能再次使用
@Test
public void test4(){
Stream<Employee> stream = emps.stream()
.filter((e) -> e.getStatus().equals(Status.FREE)); long count = stream.count(); stream.map(Employee::getSalary)
.max(Double::compare);
}

  归约

  

  备注:map和reduce的连接通常称为map-reduce模式,因Google 用它来进行网络搜索而出名。

@Test
public void test1(){
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10); Integer sum = list.stream()
.reduce(0, (x, y) -> x + y); System.out.println(sum); System.out.println("----------------------------------------");
//薪资总和
Optional<Double> op = emps.stream()
.map(Employee::getSalary)
.reduce(Double::sum); System.out.println(op.get());
}
//需求:搜索名字中 “六” 出现的次数
@Test
public void test2(){
Optional<Integer> sum = emps.stream()
.map(Employee::getName)
.flatMap(TestStreamAPI1::filterCharacter)
.map((ch) -> {
if(ch.equals('六'))
return 1;
else
return 0;
}).reduce(Integer::sum); System.out.println(sum.get());
}

  收集

  

  

    //collect——将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法
@Test
public void test3(){
List<String> list = emps.stream()
.map(Employee::getName)
.collect(Collectors.toList()); list.forEach(System.out::println); System.out.println("----------------------------------"); Set<String> set = emps.stream()
.map(Employee::getName)
.collect(Collectors.toSet()); set.forEach(System.out::println); System.out.println("----------------------------------"); HashSet<String> hs = emps.stream()
.map(Employee::getName)
.collect(Collectors.toCollection(HashSet::new)); hs.forEach(System.out::println);
}
//分组
@Test
public void test5(){
Map<Status, List<Employee>> map = emps.stream()
.collect(Collectors.groupingBy(Employee::getStatus)); System.out.println(map);
}
//多级分组
@Test
public void test6(){
Map<Status, Map<String, List<Employee>>> map = emps.stream()
.collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
if(e.getAge() >= 60)
return "老年";
else if(e.getAge() >= 35)
return "中年";
else
return "成年";
}))); System.out.println(map);
}
//分区
@Test
public void test7(){
Map<Boolean, List<Employee>> map = emps.stream()
.collect(Collectors.partitioningBy((e) -> e.getSalary() >= 5000)); System.out.println(map);
}
  Collector 接口中方法的实现决定了如何对流执行收集操作(如收集到 List、Set、Map)。但是 Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例,具体方法与实例如下表:

  

  

  

二、StreamAPI的更多相关文章

  1. Java8新特性——StreamAPI(二)

    1. 收集器简介 收集器用来将经过筛选.映射的流进行最后的整理,可以使得最后的结果以不同的形式展现. collect方法即为收集器,它接收Collector接口的实现作为具体收集器的收集方法. Col ...

  2. 010-jdk1.8版本新特性二-Optional类,Stream流

    1.5.Optional类 1.定义 Optional 类是一个可以为null的容器对象.如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象. Optional 是个 ...

  3. Java8新特性——StreamAPI 的使用

    StreamAPI的说明 Java8中有两大最为重要的改变.第一个是 Lambda 表达式:另外一个则是 Stream API. Stream API ( java.util.stream) 把真正的 ...

  4. 【小程序分享篇 二 】web在线踢人小程序,维持用户只能在一个台电脑持登录状态

    最近离职了, 突然记起来还一个小功能没做, 想想也挺简单,留下代码和思路给同事做个参考. 换工作心里挺忐忑, 对未来也充满了憧憬与担忧.(虽然已是老人, 换了N次工作了,但每次心里都和忐忑). 写写代 ...

  5. 前端开发中SEO的十二条总结

    一. 合理使用title, description, keywords二. 合理使用h1 - h6, h1标签的权重很高, 注意使用频率三. 列表代码使用ul, 重要文字使用strong标签四. 图片 ...

  6. 【疯狂造轮子-iOS】JSON转Model系列之二

    [疯狂造轮子-iOS]JSON转Model系列之二 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇<[疯狂造轮子-iOS]JSON转Model系列之一> ...

  7. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  8. 谈谈一些有趣的CSS题目(十二)-- 你该知道的字体 font-family

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

  9. MIP改造常见问题二十问

    在MIP推出后,我们收到了很多站长的疑问和顾虑.我们将所有疑问和顾虑归纳为以下二十个问题,希望对大家理解 MIP 有帮助. 1.MIP 化后对其他搜索引擎抓取收录以及 SEO 的影响如何? 答:在原页 ...

随机推荐

  1. Spring Framework5.0 学习(2)-- Quick Start

    官网:https://projects.spring.io/spring-framework/ Spring Framework 5.x 要求 JDK 1.8以上 1.0   在(1)的基础上,给bu ...

  2. Struts2注解 及 约定优于配置

    Struts2注解 1 Struts2注解的作用 使用注解可以用来替换struts.xml配置文件!!! 2 导包 必须导入struts2-convention-plugin-2.3.15.jar包, ...

  3. tensorflow训练代码

    from tensorflow.examples.tutorials.mnist import input_data import tensorflow as tf mnist = input_dat ...

  4. springboot之静态资源路径配置

    静态资源路径是指系统可以直接访问的路径,且路径下的所有文件均可被用户直接读取. 在Springboot中默认的静态资源路径有:classpath:/META-INF/resources/,classp ...

  5. C# 密封类sealed

    1.密封类定义 如果我们不希望自己编写的类被继承:如果有的类已经没有再被继承的必要,这时,我们可以使用sealed修饰符在类中进行声明,以达到该类不能派生其它类的目的,该类就被称为密封类. 2.密封类 ...

  6. MVC身份验证Attribute简易版

    public class MemberValidationAttribute : AuthorizeAttribute { protected override bool AuthorizeCore( ...

  7. 网站程序application, session, cookie区别的一点小总结

    cookie:是存放于本地的文件,可以设置期限,一般来讲是比较小文本或键值对等,主要用于记录用户浏览信息,账号密码等等.可以让人们的登录变得方便,因为有了cookie,在一段时间内就可以自动登录以前所 ...

  8. Excel2013打开提示 文件格式和扩展名不匹配。文件可能已损坏或不安全。除非您信任其来源,否则请勿打开。是否仍要打开它?

    有的时候打开xls文档时,会提示“文件格式和扩展名不匹配.文件可能已损坏或不安全.除非您信任其来源,否则请勿打开.是否仍要打开它?” 遇到这种情况,我们需要 1.win键+R键,打开“运行“,输入re ...

  9. Linux CentOs下安装lamp

    以home目录为例,进入/home cd /home 是否安装gcc与gcc-c++,没有则安装 yum -y install gcc gcc-c++ 一.安装Apache 下载httpd wget ...

  10. MySQL---正确使用索引、limit分页、执行计划、慢日志查询

    正确使用索引 数据库表中添加索引后确实会让查询速度起飞,但前提必须是正确的使用索引来查询,如果以错误的方式使用,则即使建立索引也会不奏效.即使建立索引,索引也不会生效: - like '%xx' se ...