• StreamAPI的使用


     

     

    1.    Stream 关注的是对数据的运算,与CPU打交道
        集合关注的是数据存储,与内存打交道

     2.特点

     (1) 自己不会存储元素
     (2) 不会改变源对象。相反,他们会返回一个持有结果的新的Stream
    (3) 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行

    3. Stream执行流程 

     (1) Stream实例化
    (2) 一系列的中间操作(过滤、映射...)
     (3) 终止操作

     4. 说明

     (1) 一个中间操作链,对数据源的数据进行处理
     (2) 一旦执行终止操作,就执行中间操作链,共产生结果。之后,不会再被使用

    数据准备 

    Employee类 

    1. public class Employee {
    2. private int id;
    3. private String name;
    4. private int age;
    5. private double salary;
    6. public Employee(int id, String name, int age, double salary) {
    7. this.id = id;
    8. this.name = name;
    9. this.age = age;
    10. this.salary = salary;
    11. }
    12. public Employee() {
    13. }
    14. public int getId() {
    15. return id;
    16. }
    17. public void setId(int id) {
    18. this.id = id;
    19. }
    20. public String getName() {
    21. return name;
    22. }
    23. public void setName(String name) {
    24. this.name = name;
    25. }
    26. public int getAge() {
    27. return age;
    28. }
    29. public void setAge(int age) {
    30. this.age = age;
    31. }
    32. public double getSalary() {
    33. return salary;
    34. }
    35. public void setSalary(double salary) {
    36. this.salary = salary;
    37. }
    38. @Override
    39. public String toString() {
    40. return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", salary=" + salary + "]";
    41. }
    42. @Override
    43. public int hashCode() {
    44. final int prime = 31;
    45. int result = 1;
    46. result = prime * result + age;
    47. result = prime * result + id;
    48. result = prime * result + ((name == null) ? 0 : name.hashCode());
    49. long temp;
    50. temp = Double.doubleToLongBits(salary);
    51. result = prime * result + (int) (temp ^ (temp >>> 32));
    52. return result;
    53. }
    54. @Override
    55. public boolean equals(Object obj) {
    56. if (this == obj)
    57. return true;
    58. if (obj == null)
    59. return false;
    60. if (getClass() != obj.getClass())
    61. return false;
    62. Employee other = (Employee) obj;
    63. if (age != other.age)
    64. return false;
    65. if (id != other.id)
    66. return false;
    67. if (name == null) {
    68. if (other.name != null)
    69. return false;
    70. } else if (!name.equals(other.name))
    71. return false;
    72. if (Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary))
    73. return false;
    74. return true;
    75. }
    76. }

     EmployeeData

    1. import java.util.ArrayList;
    2. import java.util.List;
    3. public class EmployeeData {
    4. public static List<Employee> getEmployee(){
    5. List<Employee> list=new ArrayList<>();
    6. list.add(new Employee(1001,"马化腾",34,6000.38));
    7. list.add(new Employee(1002,"马云",12,9876.12));
    8. list.add(new Employee(1003,"刘强东",34,3000.82));
    9. list.add(new Employee(1004,"雷军",26,7657.37));
    10. list.add(new Employee(1005,"李彦宏",65,5555.32));
    11. list.add(new Employee(1006,"比尔盖茨",42,9500.43));
    12. list.add(new Employee(1007,"任正非",26,4333.32));
    13. list.add(new Employee(1008,"扎克伯格",35,2500.32));
    14. return list;
    15. }
    16. }

    Stream的实例化方法

    1. public class StreamAPITest {
    2. /**
    3. * 测试Stream的实例化
    4. */
    5. // 创建Stream 方式一: 通过集合
    6. public void test1() {
    7. List<Employee> employees= EmployeeData.getEmployee();
    8. // default Stream<E> stream() : 返回一个顺序流
    9. Stream<Employee> stream = employees.stream();
    10. // default Stream<E> parallelStream(): 返回一个并行流
    11. Stream<Employee> parallelStream = employees.parallelStream();
    12. }
    13. //创建 Stream 方式二: 通过数组
    14. @Test
    15. public void test2() {
    16. int [] arr = {1,2,3,4,5,6};
    17. //调用Arrays类的static<T> Stream<T> stream (T [] array) :返回一个流
    18. IntStream stream = Arrays.stream(arr);
    19. Employee e1 = new Employee(100,"Tom", 0, 0);
    20. Employee e2 = new Employee(100,"Tom", 0, 0);
    21. Employee [] arr2 = {e1,e2};
    22. Stream<Employee> stream2= Arrays.stream(arr2);
    23. }
    24. //创建Stream方式三:通过Stream的of()
    25. @Test
    26. public void test3() {
    27. Stream<Integer> stream=Stream.of(1,2,3,4,5,6);
    28. }
    29. //创建Stream方式四: 创建无限流
    30. @Test
    31. public void test4() {
    32. //遍历前10个偶数
    33. Stream.iterate(0, t->t+2).limit(10).forEach(System.out::println);
    34. System.out.println("------------------");
    35. //打印10个随机小数
    36. Stream.generate(Math::random).limit(10).forEach(i->System.out.println(i));
    37. }
    38. }

    Stream的中间操作

    1. import java.util.ArrayList;
    2. import java.util.Arrays;
    3. import java.util.List;
    4. import java.util.stream.Stream;
    5. import org.junit.jupiter.api.Test;
    6. public class StreamAPITest2 {
    7. /**
    8. * 测试Stream的中间操作
    9. */
    10. // 1. 筛选和切片
    11. @Test
    12. public void test1() {
    13. List<Employee> list=EmployeeData.getEmployee();
    14. System.out.println("---------filter------");
    15. // filter(Predicate p) ----接收 Lambda,从流中排除某些元素
    16. Stream<Employee> stream=list.stream();
    17. // 练习:查询员工表中,员工工资大于7000的员工信息
    18. stream.filter(e -> e.getSalary()>7000).forEach(i->System.out.println(i));
    19. System.out.println("------limit(n)--------");
    20. //limit(n) 截断流 ,使其元素不超过给定数量
    21. list.stream().limit(3).forEach(System.out::println);
    22. System.out.println("----skip(n)------");
    23. // skip(n) --跳过元素,返回一个扔掉了前n个元素的流
    24. list.stream().skip(3).forEach(i->System.out.println(i));
    25. //distinct() --筛选,通过流所生成元素的hasnCode()和equals() 去除重复元素
    26. System.out.println("-------------------distinct-------------");
    27. list.add(new Employee(1010,"刘强东",40,8000));
    28. list.add(new Employee(1010,"刘强东",40,8000));
    29. list.add(new Employee(1010,"刘强东",40,8000));
    30. list.add(new Employee(1010,"刘强东",40,8000));
    31. list.add(new Employee(1010,"刘强东",40,8000));
    32. list.add(new Employee(1010,"刘强东",40,8000));
    33. list.stream().distinct().forEach(i->System.out.println(i));
    34. }
    35. //映射
    36. @Test
    37. public void test2() {
    38. //map (function f) --接收一个函数作为参数,将元素转换为其他形式或提取信息
    39. List<String> list = Arrays.asList("aa","bb","cc","dd");
    40. list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);
    41. //练习:获取员工姓名长度大于3的员工姓名
    42. System.out.println("---------nameStreamFilter----------");
    43. List<Employee> employees = EmployeeData.getEmployee();
    44. Stream<String> nameStream = employees.stream().map(e -> e.getName());
    45. nameStream.filter(name -> name.length()>3).forEach(System.out::println);;
    46. System.out.println("------------");
    47. //flatMap(Function f) -- 接收一个函数作为参数,将流中的每个值换位另一个流,然后把所有的流连成一个流
    48. Stream<Character> charStream = list.stream().flatMap(StreamAPITest2::fromStringToStream);
    49. charStream.forEach(System.out::println);
    50. }
    51. //将字符串中的多个字符串构成的集合转换为对应的Stream实例
    52. public static Stream<Character> fromStringToStream(String str){
    53. ArrayList<Character> list= new ArrayList<>();
    54. for(Character c:str.toCharArray()) {
    55. list.add(c);
    56. }
    57. return list.stream();
    58. }
    59. //3--排序
    60. @Test
    61. public void test4() {
    62. //sorted--自然排序
    63. System.out.println("----sorted--------");
    64. List<Integer> list = Arrays.asList(12,43,65,34,87,0,-98,7);
    65. list.stream().sorted().forEach(System.out::println);
    66. //sorted(Compare com) -- 定制排序
    67. System.out.println("------sorted(com)-----");
    68. List<Employee> employees = EmployeeData.getEmployee();
    69. employees.stream().sorted( (e1,e2)->{
    70. return (e1.getAge()-e2.getAge());
    71. } ).forEach(System.out::println);
    72. }
    73. }

    测试终止植操作

     1. 匹配和查找

    1. import java.util.List;
    2. import java.util.Optional;
    3. import java.util.stream.Stream;
    4. import org.junit.jupiter.api.Test;
    5. /**
    6. * 测试终止操作
    7. * @author CharlieLiang
    8. *
    9. */
    10. public class StreamAPITest3 {
    11. //1-- 匹配与查找
    12. @Test
    13. public void test1() {
    14. List<Employee> employees = EmployeeData.getEmployee();
    15. //allMath(Predicate p) -- 检查是否匹配所有元素
    16. // 练习:是否所有员工的年龄都大于18
    17. System.out.println("-------allMath----------");
    18. boolean allMath= employees.stream().allMatch( e -> e.getAge()>10);
    19. System.out.println(allMath);
    20. System.out.println("--------anyMatch----------");
    21. //anyMatch(Predicate p) -- 检查是否至少匹配一个袁术
    22. //练习:是否存在员工工资大于10000
    23. boolean anyMatch = employees.stream().anyMatch( e -> e.getSalary()>1000);
    24. System.out.println(anyMatch);
    25. System.out.println("----noneMath-------");
    26. //练习: 是否不存在员工姓雷
    27. boolean noneMath = employees.stream().noneMatch( e -> e.getName().startsWith("雷"));
    28. System.out.println(noneMath);
    29. System.out.println("------findFirst------");
    30. Optional<Employee> firstEmployee = employees.stream().findFirst();
    31. System.out.println(firstEmployee);
    32. System.out.println("--------findAny-----------");
    33. Optional<Employee> findAny = employees.parallelStream().findAny();
    34. System.out.println(findAny);
    35. }
    36. @Test
    37. public void test2() {
    38. List<Employee> employees = EmployeeData.getEmployee();
    39. // count -- 返回流中元素的总个数
    40. System.out.println("---------count-----------");
    41. long count = employees.stream().filter( e -> e.getSalary()>5000).count();
    42. System.out.println(count);
    43. // 练习返回最高工资
    44. System.out.println("--------max--------");
    45. Stream<Double> salaryStream = employees.stream().map( e -> e.getSalary());
    46. Optional<Double> maxSalary = salaryStream.max(
    47. (s1,s2) -> {
    48. return (int) (s1-s2);
    49. }
    50. );
    51. System.out.println(maxSalary);
    52. System.out.println("--------max2------");
    53. Stream<Double> salaryStream2 = employees.stream().map( e -> e.getSalary());
    54. Optional<Double> maxSalary2 = salaryStream2.max(Double::compare);
    55. System.out.println(maxSalary2);
    56. // 返回最低工资的员工
    57. System.out.println("---min---");
    58. Optional<Employee> minSalaryEmployee =
    59. employees.stream().min( (e1,e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
    60. System.out.println(minSalaryEmployee);
    61. //forEach (Consumer c) --- 内部迭代
    62. employees.stream().forEach(i -> System.out.println(i));
    63. // 或者
    64. // employees.forEach(System.out::println);
    65. }
    66. }

    2. 归约测试

    1. import java.util.Arrays;
    2. import java.util.List;
    3. import java.util.Optional;
    4. import java.util.stream.Stream;
    5. import org.junit.jupiter.api.Test;
    6. /**
    7. * 归约测试
    8. * @author CharlieLiang
    9. *
    10. */
    11. public class StreamAPITest4 {
    12. @Test
    13. public void test1() {
    14. //reduce (T identity, BinaryOperator) -- 可以将流中的元素反复结合起来,得到一个值。返回T
    15. // 练习计算1-10的自然数的和
    16. System.out.println("----reduce-----");
    17. List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
    18. // 0: 表示初始值是0
    19. Integer sum = list.stream().reduce(0 , Integer::sum);
    20. System.out.println(sum);
    21. System.out.println("---reduce2----");
    22. List<Integer> list2 = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
    23. // 0: 表示初始值是0
    24. Integer sum2 = list2.stream().reduce(0 , (a,b) -> (a+b));
    25. System.out.println(sum2);
    26. System.out.println("-----reduce(Optional T)---");
    27. // reduce(BinaryOperator b)--可以将流中元素反复结合起来,得到一个值。返回 Optional<T>
    28. List<Employee> employees = EmployeeData.getEmployee();
    29. Stream<Double> salaryStream = employees.stream().map(Employee::getSalary);
    30. Optional<Double> salarySum = salaryStream.reduce(Double::sum);
    31. System.out.println(salarySum);
    32. System.out.println("-----reduce(Optional T)2---");
    33. Stream<Double> salaryStream2 = employees.stream().map(Employee::getSalary);
    34. Optional<Double> salarySum2 = salaryStream2.reduce((a,b) -> (a+b) );
    35. System.out.println(salarySum2);
    36. }
    37. }

    3. 收集测试

    1. import java.util.List;
    2. import java.util.Set;
    3. import java.util.stream.Collectors;
    4. import org.junit.jupiter.api.Test;
    5. /**
    6. * 收集测试
    7. * @author CharlieLiang
    8. *
    9. */
    10. public class StreamAPITest5 {
    11. @Test
    12. public void test1() {
    13. // collect(Collector c) -- 将流转化为其他形式。接收一个Collector接口的实现,
    14. // 用于给Stream中元素做汇总的方法
    15. //练习:查找工资大于6000的员工,结果返回一个List或Set
    16. System.out.println("---toList----");
    17. List<Employee> employees = EmployeeData.getEmployee();
    18. List<Employee> empList = employees.stream().filter( e -> e.getSalary()>6000).collect(Collectors.toList());
    19. empList.forEach(System.out::println);
    20. System.out.println("---toSet----");
    21. Set<Employee> empSet = employees.stream().filter( e -> e.getSalary()>6000).collect(Collectors.toSet());
    22. empSet.forEach( i -> System.out.println(i));
    23. }
    24. }

    Optional类的使用

    介绍

     Optional类: 为了在程序中避免出现空指针异常而创建的
    常用的方法 :  ofNullable(T t)
                           ofElse(T t) 

    数据准备

    girl类 

    1. public class Girl {
    2. private String name;
    3. public Girl(String name) {
    4. this.name = name;
    5. }
    6. public Girl() {
    7. }
    8. public String getName() {
    9. return name;
    10. }
    11. public void setName(String name) {
    12. this.name = name;
    13. }
    14. @Override
    15. public String toString() {
    16. return "Girl [name=" + name + "]";
    17. }
    18. }

     Boy类

    1. public class Boy {
    2. private Girl girl;
    3. public Boy(Girl girl) {
    4. this.girl = girl;
    5. }
    6. public Boy() {
    7. }
    8. public Girl getGirl() {
    9. return girl;
    10. }
    11. public void setGirl(Girl girl) {
    12. this.girl = girl;
    13. }
    14. @Override
    15. public String toString() {
    16. return "Boy [girl=" + girl + "]";
    17. }
    18. }

    测试类 

    1. import java.util.Optional;
    2. import org.junit.jupiter.api.Test;
    3. /**
    4. * Optional类: 为了在程序中避免出现空指针异常而创建的
    5. * 常用的方法 : ofNullable(T t)
    6. * ofElse(T t)
    7. * @author CharlieLiang
    8. *
    9. */
    10. public class OptionTest {
    11. /**
    12. * Option.of(T t): 创建一个Optional实例,t必须非空
    13. * Optional.empty(): 创建一个空的Optional实例
    14. * Optional.ofNullable(T t): t可以为null
    15. */
    16. @Test
    17. public void test1() {
    18. Girl girl = new Girl();
    19. Optional<Girl> optionalGirl = Optional.of(girl);
    20. System.out.println(optionalGirl);
    21. }
    22. // ----------------------------
    23. @Test
    24. public void test2() {
    25. Girl girl = new Girl();
    26. Optional<Girl> optionalGirl = Optional.ofNullable(girl);
    27. System.out.println(optionalGirl);
    28. System.out.println("---------");
    29. Girl girl2 = null;
    30. Optional<Girl> optionalGirl2 = Optional.ofNullable(girl2);
    31. System.out.println(optionalGirl2);
    32. System.out.println("--------");
    33. //orElse(T t1) : 如果当前的Optional内部封装的t是非空的,则返回内部的t
    34. // 如果内部的t是空的,则返回orElse() 方法中的参数t1
    35. Girl girl3 = optionalGirl2.orElse( new Girl("小梅"));
    36. System.out.println(girl3);
    37. }
    38. // -----------------------------------
    39. public String getGirlName(Boy boy) {
    40. return boy.getGirl().getName();
    41. }
    42. @Test
    43. public void test3() {
    44. Boy boy = new Boy();
    45. String girlName = getGirlName(boy);
    46. System.out.println(girlName);
    47. }
    48. // ----------------------------------
    49. // 优化以后的版本
    50. public String getGirlName2(Boy boy) {
    51. if(boy != null ) {
    52. Girl girl=boy.getGirl();
    53. if(girl != null) return girl.getName();
    54. }
    55. return null;
    56. }
    57. @Test
    58. public void test4() {
    59. Boy boy = new Boy();
    60. String girlName = getGirlName2(boy);
    61. System.out.println(girlName);
    62. }
    63. // ------------------------------------
    64. // 使用Optinal类getGirlName():
    65. public String getGirlName3(Boy boy) {
    66. Optional<Boy> boyOptional = Optional.ofNullable(boy);
    67. // 此时boy2一定非空
    68. Boy boy2 = boyOptional.orElse(new Boy(new Girl("大梅")));
    69. Girl girl=boy2.getGirl();
    70. Optional<Girl> girlOptional = Optional.ofNullable(girl);
    71. // girl2 一定非空
    72. Girl girl2 = girlOptional.orElse(new Girl("小娟"));
    73. return girl2.getName();
    74. }
    75. @Test
    76. public void test5() {
    77. Boy boy = null;
    78. String girlName = getGirlName3(boy);
    79. System.out.println(girlName);
    80. System.out.println("---------");
    81. Boy boy2 = new Boy();
    82. String str= getGirlName3(boy2);
    83. System.out.println(str);
    84. System.out.println("----------");
    85. Boy boy3 = new Boy( new Girl("陈老师") );
    86. String strChen= getGirlName3(boy3);
    87. System.out.println(strChen);
    88. }
    89. }

    运行结果:

    test1

     test2

     test3

    NullPointerException

    test4

     test5

     

  • 相关阅读:
    文件操作安全之-文件上传原理篇
    ES 查询时提示:all shards failed [type=search_phase_execution_exception]
    分布式Trace:横跨几十个分布式组件的慢请求要如何排查?
    快速入门Docker
    深度学习 | Transformer 基本原理
    Metabase学习教程:仪表盘-2
    TiDB Lightning 前置检查
    SVG 和 CSS3 实现一个超酷爱心 Like 按钮
    版本控制 | 如何有效管理SVN服务器上的多个储存库
    java并发问题记录
  • 原文地址:https://blog.csdn.net/m0_46306264/article/details/125442560