Java8中Stream的使用方式

网友投稿 251 2022-08-01


目录前言:1. 为什么有经验的老手更倾向于使用Stream2. Stream 的使用方式3. Stream 的创建4. Stream 中间操作5. Stream 终止操作6. Stream 特性

前言:

相信有很多刚刚入坑程序员的小伙伴被一些代码搞的很头疼,这些代码让我们既感觉到很熟悉,又很陌生的感觉。我们很多刚入行的朋友更习惯于使用for循环或是迭代器去解决一些遍历的问题,但公司里很多老油子喜欢使用java8新特性Stream流去做,这样可以用更短的代码实现需求,但是对于不熟悉的新手来说,可读性差一些。

1. 为什么有经验的老手更倾向于使用Stream

性能优势,(大数据量)相较于迭代器,速度更快支持串行与并行处理,并行处理更能充分利用CPU的资源Stream 是一种计算数据的流,它本身不会存储数据支持函数式编程代码优雅,让代码更高效,干净,简洁

2. Stream 的使用方式

三步操作:

创建Stream中间操作终止操作

3. Stream 的创建

Stream 的 创建都会依赖于数据源,通常是容器或者数组 Stream 流的创建大致分为4中,最为常用的就是通过集合创建

import java.util.http://ArrayList;

import java.util.Arrays;

import java.util.List;

import java.util.stream.IntStream;

import java.util.stream.Stream;

public class CreateStreamDemo {

public static void main(String[] args) {

// 1 通过集合创建Stream也是用的最多的一种形式

List strList = new ArrayList<>();

strList.add("a");

strList.add("b");

strList.add("c");

// 创建串行操作流

Stream stream = strList.stream();

// 创建并行操作流

Stream parallelStream = strList.parallelStream();

// 2 通过数组创建Stream

int[] arr = new int[]{1,2,3};

IntStream intStream = Arrays.stream(arr);

// 3 通过Stream.of

Stream integerStream = Stream.of(1,2,3);

Stream stringStream = Stream.of("a","b","c");

// 4 无限流

// 每隔五个数取一个

Stream.iterate(0, t -> t + 5).forEach(System.out::println); // 迭代

Stream.generate(Math::random).forEach(System.out::println); // 生成

}

}

4. Stream 中间操作

Stream 中间操作,我们最为常用的就是过滤,去重,排序 本章包含我们开发最常用的对对象的去重,和更据对象中的对个属性组合排序

import com.zhj.java8.bean.Student;

import java.util.ArrayList;

import java.util.Comparator;

import java.util.List;

import java.util.TreeSet;

import java.util.stream.Stream;

import static java.util.stream.Collectors.collectingAndThen;

import static java.util.stream.Collectors.toCollection;

public class MiddleStreamDemo {

public static void main(String[] args) {

List students = new ArrayList<>();

students.add(new Student(1,"小华",23,1));

students.add(new Student(1,"小华",23,2));

students.add(new Student(2,"小米",20,2));

students.add(new Student(3,"小果",30,3));

students.add(new Student(4,"小维",18,2));

// 过滤

students.stream().filter(stu -> stu.getAge() > 20).forEach(System.out::println);

// 去重

// 对对象去重是根据引用去重,内容重复并不会去重,除非重写equals和hashCode方法

System.out.println("----------去重----------");

System.out.println("去重1----------");

students.stream().distinct().forEach(System.out::println);

// 对集合中对象某些属性去重,不重写equals和hashCode方法,只能借助其他数据结构来辅助去重

// 单个属性可以stu -> stu.getId()

// 多个属性可以stu -> stu.getId() + ";" + stu.getName()

System.out.println("去重2----------");

ArrayList distinctList = students.stream().collect(

collectingAndThen(toCollection(() -> new TreeSet<>(Comparator.comparing(stu -> stu.getId() + ";" + stu.getName()))), ArrayList::new)

);

distinctList.stream().forEach(System.out::println);

// 排序 支持定义排序方式

// sorted 默认使用 自然序排序, 其中的元素必须实现Comparable 接口

System.out.println("----------排序----------");

System.out.println("排序1----------");

students.stream().sorted().forEach(System.out::println);

// sorted(Comparator super T> comparator) :我们可以使用lambada 来创建一个Comparator 实例。可以按照升序或着降序来排序元素。

System.out.println("排序2----------");

students.stream()

.sorted(Comparator.comparing(Student::getAge,Comparator.reverseOrder())) // ,Comparator.reverseOrder() 逆序

.forEach(System.out::println);

// 创建比较器,通过对比较器内容的定义实现对多个属性进行排序,类似sql中连续的orderBy

System.out.println("排序3----------");

students.stream().sorted(

(s1,s2) -> {

if (s1.getAge() == s2.getAge()) {

return s1.getSex().compareTo(s2.getSex());

} else {

return -s1.getAge().compareTo(s2.getAge());

}

}

).forEach(System.out::println);

System.out.println("排序4----------");

Comparator studentComparator = (s1,s2) -> {

Integer age1 = s1.getAge();

Integer age2 = s2.getAge();

if (age1 != age2) return age1 - age2;

Integer sex1 = s1.getSex();

Integer sex2 = s2.getSex();

if (sex1 != sex2) return sex2 - sex1;

return 0;

};

students.stream().sorted(studentComparator).forEach(System.out::println);

// 截取 截取前三个元素

System.out.println("----------截取----------");

students.stream().limit(3).forEach(System.out::println);

// 跳过 跳过前3个元素

System.out.println("----------跳过----------");

students.stream().skip(3).forEach(System.out::println);

// 映射

System.out.println("----------映射----------");

System.out.println("映射Map----------");

// map接收Lambda,将元素转换其他形式,或者是提取信息,并将其映射成一个新的元素

Stream> streamStream1 = students.stream().map(str -> filterStudent(str));

streamStream1.forEach(sm -> sm.forEach(System.out::println));

System.out.println("映射flatMap----------");

// map接收Lambda,将流中的每一个元素转换成另一个流,然后把所有流连成一个流 扁平化映射

Stream studentStream2 = students.stream().flatMap(str -> filterStudent(str));

studentStream2.forEach(System.out::println);

// 消费

System.out.println("----------消费----------");

students.stream().peek(stu -> stu.setAge(100)).forEach(System.out::println);

}

public static Stream filterStudent(Student student) {

student = new Student();

return Stream.of(student);

}

}

Student

public class Student implements Comparable {

private Integer id;

private String name;

private Integer age;

private Integer sex;

public Student() {

}

public Student(Integer id, String name, Integer age, Integer sex) {

this.id = id;

this.name = name;

this.age = age;

this.sex = sex;

}

public Integer getId() {

return id;

}

public void setId(Integer id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public Integer getAge() {

return age;

}

public void setAge(Integer age) {

this.age = age;

}

public Integer getSex() {

return sex;

}

public void setSex(Integer sex) {

this.sex = sex;

}

@Override

public String toString() {

return "Student{" +

"id='" + id + '\'' +

", name='" + name + '\'' +

", age='" + age + '\'' +

", sex=" + sex +

'}';

}

@Override

public int compareTo(Student o) {

return this.getAge() - o.getAge();

}

}

5. Stream 终止操作

Stream 的终止操作,最常用的就是讲处理过的数据收集到新的容器中,同时可以实现向Sql聚合函数,分组的一些效果

package com.zhj.java8.stream;

import com.zhj.java8.bean.Student;

import java.util.*;

import java.util.stream.Collectors;

public class TerminationStreamDemo {

public static void main(String[] args) {

List students = new ArrayList<>();

students.add(new Student(1,"小华",23,1));

students.add(new Student(2,"小米",20,2));

students.add(new Student(3,"小果",30,3));

students.add(new Student(4,"小维",18,2));

students.add(new Student(5,"小华",23,2));

System.out.println("--------------------匹配聚合操作--------------------");

// allMatch:接收一个 Predicate 函数,当流中每个元素都符合该断言时才返回true,否则返回false

boolean allMatch = students.stream().allMatch(stu -> stu.getAge() > 10);

System.out.println("全部符合大于10岁条件:" + allMatch);

// noneMatch:接收一个 Predicate 函数,当流中每个元素都不符合该断言时才返回true,否则返回false

boolean noneMatch = students.stream().noneMatch(stu -> stu.getAge() > 10);

System.out.println("全部不符合大于10岁条件:" + noneMatch);

// anyMatch:接收一个 Predicate 函数,只要流中有一个元素满足该断言则返回true,否则返回false

boolean anyMatch = students.stream().anyMatch(stu -> stu.getAge() > 20);

System.out.println("含有任意符合大于20岁条件:" + anyMatch);

// findFirst:返回流中第一个元素

Student findFirst = students.stream().findFirst().get();

System.out.println("第一个学生:" + findFirst);

// findAny:返回流中的任意元素

QAaaYjBdOStudent findAny = students.stream().findAny().get();

System.out.println("任意一个学生:" + findAny);

// count:返回流中元素的总个数

long count = students.stream().count();

System.out.println("学生总数:" + count);

// max:返回流中元素最大值

Student max = students.stream().max(Student::compareTo).get();

System.out.println("年龄最大学生:" + max);

// max:返回流中元素最大值

Student min = students.stream().min(Student::compareTo).get();

System.out.println("年龄最小学生:" + min);

System.out.println("--------------------规约操作--------------------");

System.out.println("学生年龄总和:" + students.stream().map(Student::getAge).reduce(Integer::sum));

System.out.println("学生年龄最大:" + students.stream().map(Student::getAge).reduce(Integer::max));

System.out.println("--------------------收集操作--------------------");

List list = students.stream().collect(Collectors.toList());

Set set = students.stream().collect(Collectors.toSet());

Map map = students.stream().collect(Collectors.toMap(Student::getId, Student::getName));

String joinName = students.stream().map(Student::getName).collect(Collectors.joining(",", "(", ")"));

// 总数

students.stream().collect(Collectors.counting());

// 最大年龄

students.stream().map(Student::getAge).collect(Collectors.maxBy(Integer::compare)).get();

// 年龄和

students.stream().collect(Collectors.summingInt(Student::getAge));

// 平均年龄

students.stream().collect(Collectors.averagingDouble(Student::getAge));

// 信息合集

DoubleSummaryStatistics statistics = students.stream().collect(Collectors.summarizingDouble(Student::getAge));

System.out.println("count:" + statistics.getCount() + ",max:" + statistics.getMax() + ",sum:" + statistics.getSum() + ",average:" + statistics.getAverage());

// 分组

Map> collect = students.stream().collect(Collectors.groupingBy(Student::getSex));

http:// System.out.println(collect);

//多重分组,先根据性别分再根据年龄分

Map&gthttp://;> typeAgeMap = list.stream().collect(Collectors.groupingBy(Student::getSex, Collectors.groupingBy(Student::getAge)));

//分区

//分成两部分,一部分大于20岁,一部分小于等于20岁

Map> partMap = list.stream().collect(Collectors.partitioningBy(v -> v.getAge() > 20));

//规约

Integer allAge = list.stream().map(Student::getAge).collect(Collectors.reducing(Integer::sum)).get();

System.out.println(allAge);

}

}

6. Stream 特性

中间操作惰性执行

多个中间操作的话,不会多次循环,多个转换操作只会在终止操作的时候融合起来,一次循环完成。

内部迭代找到符合条件的数据后边的迭代不会进行流的末端操作只有一次

异常:stream has already been operated upon or closed

意思是流已经被关闭了,这是因为当我们使用末端操作之后,流就被关闭了,无法再次被调用,如果我们想重复调用,只能重新打开一个新的流。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java 导出Excel增加下拉框选项
下一篇:深入探究Java编程是值传递还是引用传递(java值传递和引用传递的区别是什么)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~