Stream流

Stream(流)是一个来自数据源的元素队列并支持聚合操作:

  • 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而 是按需计算。
  • 数据源 流的来源。 可以是集合,数组等。
  • 聚合操作类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted 等。

Stream流操作的三个步骤:

  1. 创建Stream

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

  2. 中间操作

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

  3. 终止操作

    一个终止操作,执行中间操作链,并产生结果

创建Stream步骤:

  • 通过Collection系列集合提供的顺序流stream()或并行流parallelStream()
  • 通过Arrays中的静态方法stream()获取数据流
  • 通过Stream类中的静态方法of()

代码实例

package com.ysh.review01_Stream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream; public class StreamTest01 {
public static void main(String[] args) {
//第一种方式:通过集合中的stream()方法创建Stream
List<String> list= Arrays.asList("红太狼","灰太狼","喜羊羊");
Stream<String> stream=list.stream();
//通过集合中的parallelStream方法创建
Stream<String> stream2 = list.parallelStream();
//第二种方式:通过java.util.Arrays下的静态方法stream创建Stream
Integer[] integer=new Integer[]{1,2,4};
//这里需要注意的是Arrays中的stream方法里面的参数需要一个数组,且数组的类型是一个引用类型或者是一个包装类
Stream<Integer> stream3 = Arrays.stream(integer);
//第三种方式:通过Stream中的of方法,实际上这种方式创建Stream实际上间接的通过调用Arrays中的stream()静态方法
Stream<String> stream4=Stream.of("a","b","c");
}
}

Stream的中间操作

筛选和切片

filter:过滤器

package com.ysh.review01_Stream;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream; public class StramTest02 {
public static void main(String[] args) {
Employee employee01=new Employee("yang","hui",29);
Employee employee02=new Employee("yang","hui",49);
Employee employee03=new Employee("yang","hui",9);
Employee employee04=new Employee("yang","hui",89);
Employee employee05=new Employee("yang","hui",89);
Employee employee06=new Employee("yang","hui",89);
List<Employee> list= Arrays.asList(employee01,employee02,employee03,employee04,employee05,employee06);
//创建Stream
Stream<Employee> stream1 = list.stream();
//对stream1流进行过滤
Stream<Employee> s = stream1.filter((e) -> {
System.out.println("---------------filter------------");
//过滤掉年龄小于19
return e.getAge() >= 19;
});
s.forEach((e-> System.out.println(e)));
}
}
class Employee {
private String id;
private String name;
private int age; public Employee() { } public Employee(String id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
} public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} @Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
return age == employee.age &&
id.equals(employee.id) &&
name.equals(employee.name);
} @Override
public String toString() {
return "Employee{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}

运行结果

skip(n):指跳过Stream中存储的前n条数据(包含第n条数据),返回后n条数据,如果n大于Stream中所有元素的个数,则返回空;(Employee类如上)

package com.ysh.review01_Stream;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream; public class StramTest02 {
public static void main(String[] args) {
Employee employee01=new Employee("yang","hui",9);
Employee employee02=new Employee("yang","hui",49);
Employee employee03=new Employee("yang","hui",9);
Employee employee04=new Employee("yang","hui",89);
Employee employee05=new Employee("yang","hui",89);
Employee employee06=new Employee("yang","hui",89);
List<Employee> list= Arrays.asList(employee01,employee02,employee03,employee04,employee05,employee06);
//创建Stream
Stream<Employee> stream1 = list.stream();
//对stream1流进行过滤
Stream<Employee> s = stream1.filter((e) -> {
System.out.println("---------------filter------------");
//过滤掉年龄小于19
return e.getAge() >= 19;
}).skip(2);
//s=s.skip(5);
s.forEach((e-> System.out.println(e)));
}
}

运行截图

distinct:筛选重复的元素,通过流生产元素的hashCode()和equals去除重复元素;

package com.ysh.review01_Stream;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream; public class StramTest02 {
public static void main(String[] args) {
Employee employee01=new Employee("yang","hui",9);
Employee employee02=new Employee("yang","hui",49);
Employee employee03=new Employee("yang","hui",9);
Employee employee04=new Employee("yang","hui",89);
Employee employee05=new Employee("yang","hui",89);
Employee employee06=new Employee("yang","hui",89);
List<Employee> list= Arrays.asList(employee01,employee02,employee03,employee04,employee05,employee06);
//创建Stream
Stream<Employee> stream1 = list.stream();
//对stream1流进行过滤
Stream<Employee> s = stream1.filter((e) -> {
System.out.println("---------------filter------------");
//过滤掉年龄小于19
return e.getAge() >= 19;
}).skip(2).distinct();
//s=s.skip(5);
s.forEach((e-> System.out.println(e)));
}
}

运行截图:

排序

sorted(Comparable)–自然排序

package com.ysh.review01_Stream;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream; public class StreamTest03 {
public static void main(String[] args) {
List<String> list= Arrays.asList("c","bbb","abc","bbbb");
Stream<String> stream = list.stream();
//即通过调用String方法中CompareTo,通过一个一个的比较字符的ASCLL值,首先比较首字符的ASCLL大小,相同的话再比较下一个
stream= stream.sorted();
stream.forEach(System.out::println);
}
}

sorted(Comparator)–定制排序

package com.ysh.review01_Stream;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream; public class StramTest02 {
public static void main(String[] args) {
Employee employee01=new Employee("yang","哈哈",19);
Employee employee02=new Employee("yang","hui",49);
Employee employee03=new Employee("yang","hui",79);
Employee employee04=new Employee("yang","呵呵呵",79);
Employee employee05=new Employee("yang","hui",39);
Employee employee06=new Employee("yang","hui",29);
List<Employee> list= Arrays.asList(employee01,employee02,employee03,employee04,employee05,employee06);
//创建Stream
Stream<Employee> stream1 = list.stream();
//对stream1流进行过滤
Stream<Employee> s = stream1.filter((e) -> {
System.out.println("---------------filter------------");
//过滤掉年龄小于19
return e.getAge() >= 19;
});
//s=s.skip(5);
/*此处可以使用Lambda表达式,即s.sorted((o1,o2)->{
//升序排序,如果年龄相同,则按照姓名的长度排序
if (o1.getAge()==o2.getAge()){
return o1.getName().length()-o2.getName().length();
}
//按照年龄升序排序
return o1.getAge()-o2.getAge(); }) */
s=s.sorted(new Comparator<Employee>() {
@Override
public int compare(Employee o1, Employee o2) {
//升序排序,如果年龄相同,则按照姓名的长度排序
if (o1.getAge()==o2.getAge()){
return o1.getName().length()-o2.getName().length();
}
//按照年龄升序排序
return o1.getAge()-o2.getAge();
}
});
s.forEach((e-> System.out.println(e)));
}
}

Stream中的map和flatMap方法:

  • 流中的每一个数据,当做map方法的参数(接口),接口中抽象方法的参数,进行制定操作,最终得到一个结果,最后所有的结果返回去成为一个流
  • 流中的每一个数据当作参数,进行操作,得到的结果必须是一个流,最终会结合成一个流返回
package com.ysh.review01_Stream;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream; public class StreamTest04 {
public static void main(String[] args) {
Stream<String> stream=Stream.of("aaa","bbbb","ccccc");
//map方法是每一个数据当作一个流,即以上{aaa}、{bbbb}、{ccccc}各是一个Stream<Character>流集合,即达到得到多个Stream<Character>流集合
//可以理解为Stream流中包含Stream<Character>流
//因为这里的testCharacter()的方法我返回的是一个Stream<Character>
//Stream<Stream<Character>> streamStream = stream.map((e) -> testCharacter(e));
Stream<Stream<Character>> streamStream = stream.map((e) -> {
List<Character> list = new ArrayList<>();
for (Character c : e.toCharArray()) {
list.add(c);
}
return list.stream();
});
streamStream.forEach((e)->{
e.forEach((e2)->{
System.out.println(e2);
});
});
Stream<String> stm=Stream.of("aaa","bbbb","ccccc");
//flatMap()方法即是把将得到的多个Stream<Character>流集合合并为一个一个Stream<Character>流集合
Stream<Character> stream1=stm.flatMap(StreamTest04::testCharacter);
//streamStream.forEach(System.out::println);
System.out.println("---------------");
stream1.forEach(System.out::println);
}
//返回一个Stream
public static Stream<Character> testCharacter(String str){
List<Character> list=new ArrayList<>();
for (Character c:str.toCharArray()){
list.add(c);
}
Stream<Character> stream=list.stream();
return stream;
}
}

终止操作

查找与匹配

  • allMatch:检查是否匹配所有元素;
  • anyMatch:检查是否至少匹配一个元素;
  • noneMatch:检查是否没有匹配所有元素;
  • findFirst:返回第一个元素;
  • findAny:返回当前流中的任意元素;
  • count:返回流中元素的总个数;
  • max:返回流中最大值;
  • min:返回流中最小值;

代码实例

package com.ysh.review01_Stream;

import java.util.Optional;
import java.util.stream.Stream; /**
* Stream中的终止操作
*/
public class StreamTest06 {
public static void main(String[] args) {
//获取Stream
Stream<String> stm1=Stream.of("aaaaaa","bbbbb","cccccc","dd","eee");
//allMatch()方法里面的参数是一个断言式接口,即实现必须重写test()方法
boolean b1 = stm1.allMatch((t) -> {
//检查是否匹配所有元素
return t.length() > 2;
});
Stream<String> stm2=Stream.of("aaaaaa","bbbbb","cccccc","dd","eee");
boolean b2=stm2.anyMatch((t) -> {
//检查是否至少匹配一个元素
return t.length() > 2;
});
Stream<String> stm3=Stream.of("aaaaaa","bbbbb","cccccc","dd","eee");
boolean b3=stm3.noneMatch((t) -> {
//检查是否没有匹配所有元素
return t.length() > 2;
});
Stream<String> stm4=Stream.of("aaaaaa","bbbbb","cccccc","dd","eee");
//得到流中的第一个元素
Optional<String> first = stm4.findFirst();
//输出
System.out.println(first.get());
Stream<String> stm5=Stream.of("aaaaaa","bbbbb","cccccc","dd","eee");
//返回当前流中的任意元素
Optional<String> any = stm5.findAny();
System.out.println(any.get());
Stream<String> stm6=Stream.of("aaaaaa","bbbbb","cccccc","dd","eee");
//放回流中元素的总个数
long count = stm6.count();
System.out.println(count);
Stream<String> stm7=Stream.of("aaaaaa","bbbbb","cccccc","dd","eee");
//返回流中最大值,即长度最长,长度相同则比较ASCLL值大小
Optional<String> max = stm7.max((s1, s2) -> {
if (s1.length()==s2.length()){
return s1.compareTo(s2);
}
return s1.length() - s2.length();
});
System.out.println(max.get());
Stream<String> stm8=Stream.of("aaaaaa","bbbbb","cccccc","dd","eee");
//返回流中最小值,即长度最短,长度相同则比较ASCLL值大小
Optional<String> min = stm8.min((s1, s2) -> {
if (s1.length() == s2.length()) {
return s2.compareTo(s1);
}
return s1.length() - s2.length();
});
System.out.println(min.get());
System.out.println(b3);
}
}

收集:

收集-将流转换为其他形式,接收一个Collertor接口的实现,用于给Stream中元素做 汇总的方法

  • List:把流中所有元素收集到List中,使用.collect(Collectors.toList());
  • Set:把流中所有元素收集到Set中,删除重复项,使用.collect(Collectors.toSet());
  • Map:把流中所有元素收集到Map中,当出现相同的key时会抛异常,使用 .collect(Collectors.toMap());
  • 使用collect方法求流中共有几条数据,使用.collect(Collectors.counting())
  • 使用collect方法求平均数,使用.collect(Collectors.averagingInt();
  • 使用collect方法求某个变量的总和,使用.collect(Collectors.summingDouble());
  • 使用collect方法且某个变量中值的最大值,使用.collect(Collectors.maxBy());

代码实例

package com.ysh.review01_Stream.one;

import java.util.*;
import java.util.stream.Collectors; public class StreamTest07 {
public static void main(String[] args) {
Student stu1=new Student("1","hhhh",18);
Student stu2=new Student("2","hhhhh",19);
Student stu3=new Student("3","oooooo",19);
Student stu4=new Student("4","aaaaa",19);
List<Student> list = Arrays.asList(stu1,stu2,stu3,stu4);
//获取所有学生的姓名流,并且存储再List集合中
List<String> collect = list.stream().map((e) -> {
return e.getName();
}).collect(Collectors.toList());
System.out.println(collect);
Set<String> set = list.stream().map((e) -> {
return e.getName();
}).collect(Collectors.toSet());
System.out.println(collect);
//将学生的姓名和年龄放入到一个集合中,当出现相同的key是会抛出一个java.lang.IllegalStateException: Duplicate key异常
Map<String, Integer> map = list.stream().collect(Collectors.toMap((e) -> e.getName(), (e2) -> e2.getAge()));
System.out.println(map);
//运用collect输出所有学生的总数
Long count2 = list.stream().collect(Collectors.counting());
System.out.println(count2);
//运用collect方法计算所有学生的平均年龄
Double collect1 = list.stream().collect(Collectors.averagingDouble((n) -> n.getAge()));
System.out.println(collect1);
//运用collect方法求所有学生的年龄之和
int agesum=list.stream().collect(Collectors.summingInt((e)->e.getAge()));
System.out.println(agesum);
//运用collect方法求所有学生中年龄最大的
Optional<Student> max2 = list.stream().collect(Collectors.maxBy((a1, a2) -> a1.getAge() - a2.getAge()));
System.out.println(max2.get()); }
}
class Student {
private String id;
private String name;
private int age;
public Student(){ } public Student(String id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
} public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} @Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
id.equals(student.id) &&
name.equals(student.name);
} @Override
public int hashCode() {
return Objects.hash(id, name, age);
} @Override
public String toString() {
return "Employee{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}

最后

感谢你看到这里,文章有什么不足还请指正,觉得文章对你有帮助的话记得给我点个赞!

Stream流的这些操作,你得知道,对你工作有很大帮助的更多相关文章

  1. Java8 Stream流API常用操作

    Java版本现在已经发布到JDK13了,目前公司还是用的JDK8,还是有必要了解一些JDK8的新特性的,例如优雅判空的Optional类,操作集合的Stream流,函数式编程等等;这里就按操作例举一些 ...

  2. 【JDK8】Java8 Stream流API常用操作

    Java版本现在已经发布到JDK13了,目前公司还是用的JDK8,还是有必要了解一些JDK8的新特性的,例如优雅判空的Optional类,操作集合的Stream流,函数式编程等等;这里就按操作例举一些 ...

  3. java中Optional和Stream流的部分操作

    package test9; import java.util.DoubleSummaryStatistics; import java.util.Optional; import java.util ...

  4. Java 基础-IO、stream 流、文件操作

    输入输出流的分类 在 java.io 包中,包含了输入输出操作所需的类. I/O 流可以安装不同的标准分类: 按照流的方向分类: 输入流:将信息从代码外部输入代码 输出流:将代码得到的数据输出到文件. ...

  5. 还看不懂同事的代码?超强的 Stream 流操作姿势还不学习一下

    Java 8 新特性系列文章索引. Jdk14都要出了,还不能使用 Optional优雅的处理空指针? Jdk14 都要出了,Jdk8 的时间处理姿势还不了解一下? 还看不懂同事的代码?Lambda ...

  6. 超强的Lambda Stream流操作

    原文:https://www.cnblogs.com/niumoo/p/11880172.html 在使用 Stream 流操作之前你应该先了解 Lambda 相关知识,如果还不了解,可以参考之前文章 ...

  7. JAVA8学习——从源码角度深入Stream流(学习过程)

    从源代码深入Stream / 学习的时候,官方文档是最重要的. 及其重要的内容我们不仅要知道stream用,要知道为什么这么用,还要知道底层是怎么去实现的. --个人注释:从此看出,虽然新的jdk版本 ...

  8. JDK8新特性---stream流

    项目上用到了stream流,找篇blog,转载一下,介绍下Stream流的用法. 1 流概述  流是 JDK8 新增的成员,允许以声明性方式处理数据集合,可以把 Stream 流看作是遍历数据集合的一 ...

  9. for循环与串行化、并行化Stream流性能对比

    第四章 并行化Stream流 关注公众号(CoderBuff)回复"stream"获取<Java8 Stream编码实战>PDF完整版. <Java8 Strea ...

随机推荐

  1. LeakCanary检测内存泄漏

    内存泄漏原因: 线程造成的内存泄漏 Handler造成的内存泄漏 单例导致内存泄露 静态变量导致内存泄露 非静态内部类导致内存泄露 未取消注册(BroadcastReceiver )或回调导致内存泄露 ...

  2. HBase进阶

    date: 2020-10-26 15:43:00 updated: 2020-10-26 18:45:00 HBase进阶 1. 架构 master负责管理多个region server,一个reg ...

  3. 【论文阅读】DGCNN:Dynamic Graph CNN for Learning on Point Clouds

    毕设进了图网络的坑,感觉有点难,一点点慢慢学吧,本文方法是<Rethinking Table Recognition using Graph Neural Networks>中关系建模环节 ...

  4. AtCoder Grand Contest 013D: Piling Up 题解

    题意简化: [luogu] Piling Up 一开始有n个颜色为黑白的球,但不知道黑白色分别有多少,m次操作,每次先拿出一个球,再放入黑白球各一个,再拿出一个球,最后拿出的球按顺序排列会形成一个颜色 ...

  5. windows搭建ftp

    控制面板                此时输入电脑用户名和密码可在自己电脑访问,但是其它电脑不能访问 接下来防火墙允许的应用将FTP服务器打钩 控制面板\系统和安全\Windows Defender ...

  6. LWJGL3的内存管理

    LWJGL3的内存管理 LWJGL3 (Lightweight Java Game Library 3),是一个支持OpenGL,OpenAl,Opengl ES,Vulkan等的Java绑定库.&l ...

  7. IDEA创建maven项目没有src/main/java目录问题解决

    IDEA创建maven项目没有src/main/java目录问题解决          今天新建一个maven项目的时候,没有src文件目录,查了网上很多,依然没有解决,后来发现是VM Options ...

  8. layui表单提交与ajax访问webapi

    啊啊啊啊 这个东西实在很蛋疼啊 每次访问webapi就很老火 这里就一下  以后忘记的话就来查阅 不多说 直接开始 首先html页面 新建一个基于layui的form表单页面LayuiForm.csh ...

  9. Boltzmann Machine 玻尔兹曼机入门

    Generative Models 生成模型帮助我们生成新的item,而不只是存储和提取之前的item.Boltzmann Machine就是Generative Models的一种. Boltzma ...

  10. 批处理最小二乘法 python

    参考:系统辨识与自适应控制MATLAB仿真(修订版) 庞中华 崔红 仿真实例2.5 import numpy as np import matplotlib.pyplot as plt from mx ...