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. Java实现:抛开jieba等工具,写HMM+维特比算法进行词性标注

    一.前言:词性标注 二.经典维特比算法(Viterbi) 三.算法实现 四.完整代码 五.效果演示: 六.总结 一.前言:词性标注 词性标注(Part-Of-Speech tagging, POS t ...

  2. Vue内容

    vue中的过滤器 moeths点击 过滤器的含义 过滤器就是把原有的数据过一遍 放到页面中  不会改变原有的数据   只是在原有的数据上增加新的数据

  3. Stream(三)

    public class Test08 { /* * 二.中间的加工操作 * (1)filter(Predicate p):过滤 * (2)distinct():去重 * (3)limit(long  ...

  4. Redis【二】 set|get那些事

    redis4.0.9 SET\GET方法 从哪里开始 server.c里面有每个redis命令对应的执行方法 如 struct redisCommand redisCommandTable[] = { ...

  5. (python)getattr等用法

    getattr() 函数用于返回一个对象属性值; 语法 getattr(object, name[, default]) 参数 object -- 对象. name -- 字符串,对象属性. defa ...

  6. oracle ql/sql 相关语法解析

    这篇文章主要介绍了Oracle中游标Cursor基本用法详解,还是比较全面的,具有一定参考价值,需要的朋友可以了解下.   查询 SELECT语句用于从数据库中查询数据,当在PL/SQL中使用SELE ...

  7. 开发工具:Mybatis.Plus.插件三种方式的逆向工程

    本文源码:GitHub·点这里 || GitEE·点这里 一.逆向工程简介 在Java开发中,持久层最常用的框架就是mybatis,该框架需要编写sql语句,mybatis官方提供逆向工程,可以把数据 ...

  8. python机器学习实现人脸图片自动补全

    人脸自动补全 关注公众号"轻松学编程"了解更多. 1.导包 import matplotlib.pyplot as plt import numpy as np import pa ...

  9. java socket 字节操作

    原文链接: http://blog.csdn.net/hslinux/article/details/6214594 java与C++之间进行SOCKET通讯要点简要解析 hslinux 0.篇外语 ...

  10. Cuda常用概念及注意点

    线程的索引计算 只需要知并行线程的初始索引,以及如何确定递增的量值,我们希望每个并行线程从不同的索引开始,因此就需要对线程索引和线程块索引进行线性化,每个线程的其实索引按照以下公式来计算: int t ...