文章目录
Stream流
1、Stream介绍
Stream是一个流,在java.util.Stream包路径下
主要作用就是对集合数据进行查找过滤等操作,一种高效且易用的数据处理方式
大数据领域有一个Stream流实时框架
Stream和Collection的区别就是:
Collection只是负责存储数据,不对数据做其他处理主要和内存打交道。
Stream主要是负责计算数据的,主要和CPU打交道(查询过滤)
2、Stream的操作
stream().后的操作汇总
方法 | 作用 |
---|---|
filter() | 接收lambda,从流中排除某些操作 |
limit() | 截断流,使其元素不超过给定对象 |
skip(n) | 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补 |
distinct | 筛选,通过流所生成元素的hashCode()和equals去除重复元素 |
map | 接受Lambda,将元素转换成其他形式或提取信息。接受一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素 |
sorted() | 自然排序(Comparable) |
sorted(Comparator com) | 定制排序(Comparator) |
allMatch | 检查是否匹配所有元素 |
anyMatch | 检查是否至少匹配一个元素 |
noneMatch | 检查是否没有匹配所有元素 |
findFirst | 返回第一个元素 |
findAny | 返回当前流中的任意元素 |
count | 返回流中元素的总个数 |
max | 返回流中最大值 |
min | 返回流中最小值 |
reduce | 归约操作可以将流中元素反复结合起来,得到一个值 |
collect | 将流转换为其他形式,接收一个Collector接口实现,用于给Stream中汇总的方法 |
(流程较简单)
1、创建一个Stream:从一个数据源,如集合、数组中获取流
2、使用Stream操作数据:一个操作的中间链,对数据源的数据进行操作
3、终止Stream:一个终止操作,执行中间操作链,并产生结果
1)创建流
首先建一个数据源
public class Student implements Comparable{
private Integer id;
private String name;
private Integer age;
private Double score;
public Student(Integer id, String name, Integer age, Double score) {
this.id = id;
this.name = name;
this.age = age;
this.score = score;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
public Double getScore() {
return score;
}
public void setId(Integer id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
public void setScore(Double score) {
this.score = score;
}
@Override
public int compareTo(Object o) {
Student o1=(Student)o;return o1.getAge()-this.getAge();
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
import java.util.ArrayList;
import java.util.List;
public class StudentData {
public static List <Student> getStudents(){
ArrayList <Student> students=new ArrayList<>();
students.add(new Student(1,"jack",23,89.5));
students.add(new Student(2,"jony",22,90.5));
students.add(new Student(3,"Alice",22,87.1));
students.add(new Student(4,"dack",24,89.7));
return students;
}
}
有四种创建流的方式
a、.stream()
调用stream()方法直接返回流
public static void test1() {
List<Student> students = StudentData.getStudents();
Stream<Student> stream = students.stream();//第一种:返回一个顺序流
Stream<Student> stream1 = students.parallelStream();//第二种:返回一个并行流
}
b、Arrays.stream()
//通过一个数组创建stream
public static void test2(){
//获取一个整型stream
int []arr={1,34,2,54,56,34};
IntStream stream = Arrays.stream(arr );
}
c、stream.of
public static void test3(){
Stream<String> stringStream =Stream .of("1","4","34","23");
Stream<Student>studentStream =Stream .of(new Student(1,"book",23,89.5),
new Student(2,"cack",22,90.9));
}
d、无限流
//创建无限流
public static void test4(){
//每隔5个数取一个,从0开始,此时就会无限循环
//t->t+5 ___________ for(int t=0;;){t+=5;}
Stream <Integer>iterate=Stream.iterate(0,t->t+5);
//取出一个随机数
Stream <Double> generate=Stream.generate(Math ::random );
}
2)使用流
a
操作一:筛选和切片
filter——接收lambda,从流中排除某些操作;
limit——截断流,使其元素不超过给定对象
skip(n)——跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补
distinct——筛选,通过流所生成元素的hashCode()和equals去除重复元素
public static void test5(){
/**
* 写成System.out::println这种语法叫做方法引用。该功能特性也是JDK8以后引入的,你可以把它看成lambdas表达式的语法糖
* 可以用lambdas表达式改写成以下代码:list.forEach(t)-》System.out.println(t);
* 这样还不明白的话,也可以这样:list.forEach(String t)-》System.out.println(t);
* 这样的效果跟System.out::println是一样
*/
List <Student> list=StudentData.getStudents();
//过滤:过滤出所有年龄大于22岁的同学
System.out.println("=============");
list.stream().filter(item->item.getAge()>22).forEach(System.out::println);
//截断流:筛选出前三条
list.stream().limit(3).forEach(System.out::println);
//跳过元素:跳过前两个元素
list.stream().skip(2).forEach(System.out::println);
System.out.println("================");
//过滤重复元素
list.stream().distinct().forEach(System.out::println);//没有重复的,根据hashcode判断
}
b
操作二:映射
map——接受Lambda,将元素转换成其他形式或提取信息。接受一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
public static void test6(){
//map操作
List<String>list=Arrays.asList("hello","word","tulun");
Stream<String> stream =list .stream() ;
//将每一个小写字母都转换为大写字母映射
stream .map(str ->str.toLowerCase()).forEach(System.out::println);
//筛选出所有的年龄,再过滤出所有大于23的年龄
List<Student>students =StudentData .getStudents() ;
Stream <Student >stream1 =students .stream() ;
//将流中的每一值转换为另一个值
Stream <Integer >stream2 =stream1 .map(Student::getAge );
stream2 .filter(age->age>23).forEach(System.out::println);
}
c
操作三:排序
sorted()——自然排序(Comparable)
sorted(Comparator com)——定制排序(Comparator)
public static void tset7(){
//自然排序
List <Integer >list=Arrays .asList(4,8,6,5,2,3,1,7);
Stream<Integer >stream =list.stream() ;
stream .sorted() .forEach(System.out::println );
//对象排序,对象排序可以先实现comparable接口或者直接指定
//第一种:先实现
List<Student> students =StudentData .getStudents() ;
students .stream() .sorted() .forEach(System.out::println);
//第二种:直接指定
List<Student> students1 =StudentData .getStudents() ;
students1 .stream() .sorted((e1,e2)->(int)(e1.getScore() -e2.getScore() )).forEach(System.out::println);
}
3)终止Stream
a
操作1:匹配和查找
*allMatch–检查是否匹配所有元素
*anyMatch–检查是否至少匹配一个元素
*noneMatch–检查是否没有匹配所有元素
*findFirst–返回第一个元素
*findAny–返回当前流中的任意元素
*count–返回流中元素的总个数
*max–返回流中最大值
*min–返回流中最小值
public static void test8(){
List<Student> list=StudentData.getStudents() ;
//判断所有的学生年龄是否都大于20岁
boolean allMatch=list.stream() .allMatch(student ->student .getAge() >20);
//判断是否存在学生的年龄大于20岁
boolean anyMatch=list .stream() .anyMatch(student ->student .getAge() >20);
//判断是否不存在学生叫小白
boolean noneMatch=list .stream() .noneMatch(student ->student .getName() .equals("小白") );
//查找第一个学生
Optional<Student>first=list .stream() .findFirst() ;
//查找当前流中的元素
Optional <Student>any=list .stream() .findAny() ;
//查找所有的学生数量
long count=list .stream() .count() ;
//查找成绩大于90的数量
long count1=list .stream() .filter(student ->student .getScore() >90).count() ;
//查找学生的最高分数
Stream <Double >doubleStream =list .stream() .map(student ->student .getScore() );
Optional <Double > max=doubleStream .max(Double::compareTo );
System.out.println(max );
}
b
操作二:归约
*reduce–归约操作可以将流中元素反复结合起来,得到一个值
public static void test9(){
//计算数的总和
List<Integer >list =Arrays .asList(4,5,6,1,8,9,2,3,7) ;
Integer reduce=list .stream() .reduce(0,Integer::sum );
System.out.println(reduce );
//计算学生总分
List <Student >students =StudentData .getStudents() ;
Stream <Double >doubleStream =students .stream() .map(Student::getScore );
Optional <Double >reduce1=doubleStream .reduce(Double ::sum );
System.out.println(reduce1 .get() );
}
c
操作三:收集
*collect:将流转换为其他形式,接收一个Collector接口实现,用于给Stream中汇总的方法
public static void test10(){
//返回一个list
List <Student >students =StudentData .getStudents() ;
List <Student >list =students .stream() .filter(student ->student .getScore() >88).collect(Collectors.toList()) ;
//返回一个set
Set <Student >set =students .stream() .filter(s->s.getAge() >23).collect(Collectors.toSet()) ;
System.out.println(set );
}
3、Stream的优势
stream基本的语法就是这样,你会发现Stream就像是一个工具一样,可以帮我们分析处理数据,极其的好用,但是目前还不知道其效率如何
根据网上一位大佬的内存时间分析,其实在数据量比较庞大的时候,Stream可以为我们节省大量的时间