• JDK1.8新特性之stream流及日期


    目录

    1.什么是Stream

    2.为什么使用Stream

    3.Stream流的操作原理

    4.如何获取Stream流对象

    5.Stream流中常见的api

    6.新增了日期时间类


    1.什么是Stream

            Stream 是Java8中处理集合的关键抽象概念,它可以对集合进行非常复杂的查找、过滤、筛选等操作。

    2.为什么使用Stream

            当我们需要对集合中的元素进行操作的时候,除了必需的添加、删除、获取外,最典型的就是集合遍历。

            例如:一个ArrayList集合中存储数据;需求:1.拿到所有姓张的 2.拿到名字长度为3个字的 3.打印这些数据,此时代码:

    1. public class My {
    2. public static void main(String[] args) {
    3. // 一个ArrayList集合中存储有以下数据:张无忌,周芷若,赵敏,张强,张三丰
    4. // 需求:1.拿到所有姓张的 2.拿到名字长度为3个字的 3.打印这些数据
    5. ArrayList list = new ArrayList<>();
    6. Collections.addAll(list, "张一一","张一","张二二","王一","李一","张三");
    7. // 1.拿到所有姓张的
    8. ArrayList zhangList = new ArrayList<>();
    9. for (String name : list) {
    10. if (name.startsWith("张")) {
    11. zhangList.add(name);
    12. }
    13. }
    14. // 2.拿到名字长度为3个字的
    15. ArrayList threeList = new ArrayList<>();
    16. for (String name : zhangList) {
    17. if (name.length() == 3) {
    18. threeList.add(name);
    19. }
    20. }
    21. // 3.打印这些数据
    22. for (String name : threeList) {
    23. System.out.println(name);
    24. }
    25. }
    26. }

    这段代码中含有三个循环,每一个作用不同:

    1. 首先筛选所有姓张的人;

    2. 然后筛选名字有三个字的人;

    3. 最后进行对结果进行打印输出。

    每当我们需要对集合中的元素进行操作的时候,总是需要进行循环、循环、再循环。这是理所当然的么?不是。循环 是做事情的方式,而不是目的。每个需求都要循环一次,还要搞一个新集合来装数据,如果希望再次遍历,只能再使用另一个循环从头开始。

            使用Stream流来改写代码:

    1. public class OpenTest {
    2. public static void main(String[] args) {
    3. List list=new ArrayList<>();
    4. Collections.addAll(list,"张一一","张一","张二二","王一","李一","张三");
    5. list.stream()
    6. //底层使用断言函数式,有参有boolean返回值
    7. .filter((item)->item.startsWith("张"))
    8. .filter(item->item.length()==3)
    9. .forEach(item-> System.out.println(item));
    10. }
    11. }

    对集合的操作语法简洁:性能比传统快。

    3.Stream流的操作原理

    注意:Stream和IO流(InputStream/OutputStream)没有任何关系,请暂时忘记对传统IO流的固有印象!

    Stream流式思想类似于工厂车间的“生产流水线”,Stream流不是一种数据结构不保存数据,而是对数据进行加工处理。Stream可以看作是流水线上的一个工序。在流水线上,通过多个工序让一个原材料加工成一个商品。

    Stream不存在数据,只对数据进行加工处理。

    4.如何获取Stream流对象

    (1)通过Collection对象的stream()或parallelStream()方法

    (2)通过Arrays类的stream()方法

    (3)通过Stream接口的of()、iterate()、generate()方法

    (4)通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法

    练习代码展示:

    1. public class getStreamMethods {
    2. public static void main(String[] args) {
    3. //通过集合对象调用stream()获取流
    4. List list=new ArrayList<>();
    5. Collections.addAll(list,"张三","李四","王五","赵六");
    6. Stream stream = list.stream();
    7. //通过Arrays数组工具类获取Stream对象
    8. int[] arr={3,45,23,33,67};
    9. IntStream stream1 = Arrays.stream(arr);
    10. //使用Stream类中of方法
    11. Stream.of("hello","world","spring","java");
    12. //LongStream range不包括右侧
    13. //LongStream rangeClosed包括右侧
    14. LongStream range = LongStream.range(1, 10);
    15. range.forEach(item-> System.out.println(item));
    16. //上面都是获取的串行流。 还可以获取并行流。如果流中的数据量足够大,并行流可以加快处理速度
    17. Stream stringStream = list.parallelStream();
    18. stringStream.forEach(item-> System.out.println(item));
    19. //或者是此款样式输出信息
    20. //stringStream.forEach(System.out::println);
    21. }
    22. }

    5.Stream流中常见的api

            中间操作api: 一个操作的中间链,对数据源的数据进行操作。而这种操作的返回类型还是一个Stream对象。

            终止操作api: 一个终止操作,执行中间操作链,并产生结果,返回类型不在是Stream流对象。

    (1)filter / foreach / count

    (2) map | sorted

            map--接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

     

    1. //对流中元素排序
    2. personList.stream()
    3. .sorted((o1,o2)->o1.getAge()-o2.getAge())
    4. .forEach(System.out::println);
    5. //集合中每个元素只要名.map--->原来流中每个元素转换为另一种格式。
    6. // personList.stream()
    7. // .map(item->{
    8. // Map m=new HashMap<>();
    9. // m.put("name",item.getName());
    10. // m.put("age",item.getAge());
    11. // return m;
    12. // })
    13. // .forEach(System.out::println);

    (3) min max

     (4)规约reduce

     (5)collect搜集 match find

    总代码展示:

    1. public class GetStreamApi {
    2. public static void main(String[] args) {
    3. List personList = new ArrayList<>();
    4. personList.add(new Person("欧阳雪",18,"中国",'F'));
    5. personList.add(new Person("Tom",24,"美国",'M'));
    6. personList.add(new Person("Harley",22,"英国",'F'));
    7. personList.add(new Person("向天笑",20,"中国",'M'));
    8. personList.add(new Person("李康",22,"中国",'M'));
    9. personList.add(new Person("小梅",20,"中国",'F'));
    10. personList.add(new Person("何雪",21,"中国",'F'));
    11. personList.add(new Person("李康",22,"中国",'M'));
    12. //findFirst(找第一个出现的符合要求的Person类) match
    13. Optional first = personList.stream()
    14. .filter(item -> item.getSex() == 'F')
    15. .findFirst();
    16. System.out.println(first);
    17. System.out.println("=================================================");
    18. //findAny(找随机出现的符合要求的Person类,注意使用并发类) match
    19. Optional any = personList.parallelStream()
    20. .filter(item -> item.getSex() == 'M')
    21. .findAny();
    22. System.out.println(any);
    23. System.out.println("=====================================================");
    24. //match: allMatch 符合前边条件的同时又符合现在条件的所有Person类 为true
    25. //match: anyMatch 符合前边条件的同时又符合现在条件的任一Person类 为true
    26. //match: noneMatch 符合前边条件的同时不符合现在条件的任一Person类 为true
    27. boolean b1 = personList.stream()
    28. .filter(item -> item.getSex() == 'F').allMatch(item -> item.getAge() >= 20);
    29. System.out.println(b1);
    30. System.out.println("===========================================");
    31. //搜索方法collect 属于终止方法
    32. //年龄大于20且性别为M
    33. List collect = personList.stream()
    34. .filter(item -> item.getAge() > 20)
    35. .filter(item -> item.getSex() == 'M')
    36. .collect(Collectors.toList());
    37. System.out.println(collect);
    38. System.out.println("====================================");
    39. //求集合中所有人的年龄和 参数和返回类型必须一致
    40. Optional reduce = personList.stream()
    41. .map(item -> item.getAge())
    42. .reduce((a, b) -> a + b);
    43. System.out.println(reduce.get());
    44. System.out.println("====================================");
    45. //求集合中所有人的年龄和+10 参数和返回类型必须一致
    46. Integer reduce1 = personList.stream()
    47. .map(item -> item.getAge())
    48. .reduce(10, (a, b) -> a + b);
    49. System.out.println(reduce1);
    50. System.out.println("====================================");
    51. //求名字最长的员工
    52. Optional max1 = personList.stream()
    53. .max((o1, o2) -> o1.getName().length() - o2.getName().length());
    54. System.out.println(max1.get());
    55. System.out.println("===================================");
    56. //查找最大年龄的人,max终止操作
    57. Optional max = personList.stream().max((o1, o2) -> o1.getAge() - o2.getAge());
    58. System.out.println(max.get());
    59. System.out.println("===================================");
    60. //查找最小年龄的人,min终止操作
    61. Optional min = personList.stream().min((o1, o2) -> o1.getAge() - o2.getAge());
    62. System.out.println(min.get());
    63. System.out.println("===================================");
    64. //集合中每个元素只要名及年龄,map---》原来流中每个元素转换为另一种格式
    65. personList.stream()
    66. .map(item->{
    67. Map m=new HashMap<>();
    68. m.put("name",item.getName());
    69. m.put("age",item.getAge());
    70. return m;
    71. })
    72. .forEach(System.out::println);
    73. //对流中元素排序
    74. personList.stream()
    75. .sorted((o1,o2)->o1.getAge()-o2.getAge())
    76. .forEach(System.out::println);
    77. System.out.println("===============================================");
    78. //找到年龄大于18的并输出 ; filter()过滤器需要一个断言接口函数,断言接口返回true,获取该元素 , forEach()遍历
    79. //无论执行多少个中间操作,如果没有执行终止操作,那么 中间操作都不会被执行
    80. personList.stream()
    81. .filter(item->item.getAge()>18)
    82. .forEach(System.out::println);
    83. //找出所有中国人的数量 filter()过滤器,过滤其他国家的人 count()终止操作
    84. long count = personList.stream().filter(item -> item.getCountry().equals("中国")).count();
    85. System.out.println(count);
    86. //找到性别M的并输出 ; filter()过滤器需要一个断言接口函数,断言接口返回true,获取该元素 ,
    87. long count1 = personList.stream().filter(item -> item.getSex() == 'M').count();
    88. System.out.println(count1);
    89. }
    90. }
    91. class Person {
    92. private String name;
    93. private Integer age;
    94. private String country;
    95. private char sex;
    96. @Override
    97. public String toString() {
    98. return "Person{" +
    99. "name='" + name + '\'' +
    100. ", age=" + age +
    101. ", country='" + country + '\'' +
    102. ", sex=" + sex +
    103. '}';
    104. }
    105. public String getName() {
    106. return name;
    107. }
    108. public void setName(String name) {
    109. this.name = name;
    110. }
    111. public Integer getAge() {
    112. return age;
    113. }
    114. public void setAge(Integer age) {
    115. this.age = age;
    116. }
    117. public String getCountry() {
    118. return country;
    119. }
    120. public void setCountry(String country) {
    121. this.country = country;
    122. }
    123. public char getSex() {
    124. return sex;
    125. }
    126. public void setSex(char sex) {
    127. this.sex = sex;
    128. }
    129. public Person(String name, Integer age, String country, char sex) {
    130. this.name = name;
    131. this.age = age;
    132. this.country = country;
    133. this.sex = sex;
    134. }
    135. }

    6.新增了日期时间类

    旧的日期时间的缺点:

    1. 设计比较乱: Date日期在java.util和java.sql也有,而且它的时间格式转换类在java.text包。

    2. 线程不安全。

     新增加了哪些类?

    LocalDate:表示日期类。yyyy-MM-dd

    LocalTime:表示时间类。HH:mm:ss

    LocalDateTime:表示日期时间类yyyy-MM-dd t HH:mm:ss sss

    DatetimeFormatter:日期时间格式转换类。

    Instant:时间戳类

    Duration:用于计算两个日期类

    代码展示:

    1. public class NewDateTest {
    2. public static void main(String[] args) {
    3. LocalDate now1 = LocalDate.now();//获取当前日期时间
    4. System.out.println(now1);
    5. LocalDate now2 = LocalDate.of(2022, 6, 20);//指定日期
    6. System.out.println(now2);
    7. LocalTime now3 = LocalTime.now();//获取当前日期时间
    8. System.out.println(now3);
    9. LocalTime of = LocalTime.of(17,30,20);//指定时间
    10. System.out.println(of);
    11. LocalDateTime now = LocalDateTime.now();//获取当前日期时间
    12. LocalDateTime of1 = LocalDateTime.of(2022, 7, 1, 20, 15, 20);
    13. Duration between = Duration.between(now, of1);
    14. System.out.println(between.toDays());//两端时间差
    15. DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    16. LocalDate parse = LocalDate.parse("1992-12-12", dateTimeFormatter);//把字符串转换为日期格式
    17. System.out.println(parse);
    18. }
    19. }

  • 相关阅读:
    MATLAB垃圾分类识别
    【C++刷题集】-- day3
    uniapp HBuilder 无法运行微信小程序的问题解决
    区块链技术研究探讨
    交换两个数值(不用第三个变量
    论文阅读《ESSWC2018:Modeling Relational Data with Graph Convolutional Networks》
    六、ROS2通信机制(服务)
    微服务Eureka注册中心地址配置不生效
    罗马数字转整数
    【C++11并发】thread 笔记
  • 原文地址:https://blog.csdn.net/qq_50896786/article/details/125900807