六、Stream API

Java8中有两大最为重要的改变。第一个是 Lambda 表达式;另外一个则是 Stream API(java.util.stream.*)。Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式

流(Stream) 到底是什么呢?
是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。“集合讲的是数据,流讲的是计算!”
注意:
①Stream 自己不会存储元素。
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。(也就是中间操作不会立即执行)

Stream操作分为三个步骤

 1、创建 Stream一个数据源(如:集合、数组),获取一个流

2、中间操作一个中间操作链,对数据源的数据进行处理

  3、终止操作(终端操作)一个终止操作,执行中间操作链,并产生结果

 步骤一:创建Stream的四种方式

  1. package com.bjsxt.stream;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.Arrays;
  5. import java.util.List;
  6. import java.util.stream.Stream;
  7.  
  8. /**
  9. * stream的三个步骤
  10. * 1、创建stream
  11. * 2、中间操作
  12. * 3、终止操作(终端操作)
  13. */
  14. public class TestStream01 {
  15.  
  16. public static void main(String[] args){
  17. test01();
  18. }
  19.  
  20. /**
  21. * 创建stream的四种方式
  22. */
  23. public static void test01(){
  24. // 1、可以通过Collection系列集合提供的stream()或parallelStream()
  25. List<String> list=new ArrayList<String>();
  26. Stream<String> stream=list.stream();
  27.  
  28. // 2、可以通过Arrays中的静态方法stream()获取数据流
  29. String[] strArr=new String[10];
  30. Stream<String> stream2=Arrays.stream(strArr);
  31.  
  32. // 3、通过Stream类中的静态方法of()
  33. Stream<String> stream3=Stream.of("aa","bb","cc");
  34.  
  35. // 4、创建无限流
  36. //方式一:迭代,使用Stream.iterate()方法
  37. Stream<Integer> stream4=Stream.iterate(0,(x)->x+2);
  38.  
  39. //方式二:生成,使用Stream.generate()方法
  40. Stream<Double> stream5=Stream.generate(()->Math.random());
  41. stream5.forEach(System.out::println); //这个forEach()方法是终端操作,打印用
  42. }
  43. }

步骤二:中间操作

  多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值”。

  中间操作有很多种,主要有三种

  1、筛选与切片

  1. package com.bjsxt.stream;
  2.  
  3. import com.bjsxt.Person;
  4.  
  5. import java.util.Arrays;
  6. import java.util.List;
  7. import java.util.stream.Stream;
  8.  
  9. /**
  10. * stream
  11. * 中间操作
  12. */
  13. public class TestStream02 {
  14.  
  15. public static List<Person> list= Arrays.asList(
  16. new Person(1,"段然涛",18),
  17. new Person(2,"李飞宇",34),
  18. new Person(3,"卢晓倩",25),
  19. new Person(4,"李小静",67),
  20. new Person(4,"李小静",67),
  21. new Person(4,"李小静",67),
  22. new Person(5,"罗泽成",12)
  23. );
  24.  
  25. public static void main(String[] args){
  26.  
  27. }
  28.  
  29. /**
  30. * filter()方法
  31. */
  32. public static void tesst01(){
  33. Stream<Person> stream=list.stream(); //获取流
  34. stream.filter((per)->per.age>18) //filter()接收 Lambda , 从流中排除某些元素,会进行隐式迭代
  35. .forEach(System.out::println); //这个是终端操作,这里使用只是方便打印
  36. }
  37.  
  38. /**
  39. * limit()方法
  40. */
  41. public static void tesst02(){
  42. Stream<Person> stream=list.stream(); //获取流
  43. stream.filter((per)->per.age>18) //filter()接收 Lambda , 从流中排除某些元素
  44. .limit(2) //截断流,使其元素不超过给定数量。也就是只要筛选出来的前两个,这里操作类似于短路(&&),当筛选出来两个后,后面的就不再迭代,提高效率
  45. .forEach(System.out::println); //这个是终端操作,这里使用只是方便打印
  46. }
  47.  
  48. /**
  49. * skip()方法
  50. */
  51. public static void tesst03(){
  52. Stream<Person> stream=list.stream(); //获取流
  53. stream.filter((per)->per.age>18) //filter()接收 Lambda , 从流中排除某些元素
  54. .skip(2) //跳过前两个元素,跟limit刚好相反
  55. .forEach(System.out::println); //这个是终端操作,这里使用只是方便打印
  56. }
  57.  
  58. /**
  59. *distinct()方法
  60. */
  61. public static void tesst04(){
  62. Stream<Person> stream=list.stream(); //获取流
  63. stream.filter((per)->per.age>18) //filter()接收 Lambda , 从流中排除某些元素
  64. .distinct() //筛选,通过流所生成元素的 hashCode() 和 equals() 去 除重复元素
  65. .forEach(System.out::println); //这个是终端操作,这里使用只是方便打印
  66. }
  67. }

  2、映射

  

  1. package com.bjsxt.stream;
  2.  
  3. import com.bjsxt.Person;
  4.  
  5. import java.util.ArrayList;
  6. import java.util.Arrays;
  7. import java.util.List;
  8. import java.util.stream.Stream;
  9.  
  10. /**
  11. * stream
  12. * 中间操作
  13. */
  14. public class TestStream03 {
  15.  
  16. public static List<Person> list= Arrays.asList(
  17. new Person(1,"段然涛",18),
  18. new Person(2,"李飞宇",34),
  19. new Person(3,"卢晓倩",25),
  20. new Person(4,"李小静",67),
  21. new Person(4,"李小静",67),
  22. new Person(4,"李小静",67),
  23. new Person(5,"罗泽成",12)
  24. );
  25.  
  26. public static void main(String[] args){
  27. tesst02();
  28. }
  29.  
  30. /**
  31. * map()方法
  32. */
  33. public static void tesst01(){
  34. Stream<Person> stream=list.stream(); //获取流
  35. stream.map((person -> person.getName())) //接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
  36. .forEach(System.out::println);
  37. System.out.println("-----------------------------------------------------------------------------");
  38. List<String> list=Arrays.asList("aa","bb","cc");
  39. list.stream().map(str->str.toUpperCase())
  40. .forEach(System.out::println);
  41.  
  42. }
  43.  
  44. /**
  45. * flatMap()方法
  46. */
  47. public static void tesst02(){
  48. List<String> strList = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
  49. Stream<Stream<Character>> stream=strList.stream().map(TestStream03::splitString);
  50. stream.forEach(sm->sm.forEach(System.out::println)); //如果使用map需要这样遍历
  51.  
  52. System.out.println("------------------------------");
  53. /**
  54. * map和flatMap的区别就如集合中add(集合)和addAll(集合)的区别
  55. */
  56. Stream<Character> stream2 = strList.stream()
  57. .flatMap(TestStream03::splitString); //接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
  58. stream2.forEach(System.out::println);
  59.  
  60. }
  61.  
  62. public static Stream<Character> splitString(String str){
  63. List<Character> list=new ArrayList<Character>();
  64. for(Character c:str.toCharArray()){
  65. list.add(c);
  66. }
  67. return list.stream();
  68. }
  69. }

  3、排序

  1. package com.bjsxt.stream;
  2.  
  3. import com.bjsxt.Person;
  4.  
  5. import java.util.ArrayList;
  6. import java.util.Arrays;
  7. import java.util.List;
  8. import java.util.stream.Stream;
  9.  
  10. /**
  11. * stream
  12. * 中间操作
  13. */
  14. public class TestStream04 {
  15.  
  16. public static List<Person> list= Arrays.asList(
  17. new Person(1,"段然涛",18),
  18. new Person(2,"李飞宇",34),
  19. new Person(3,"卢晓倩",25),
  20. new Person(4,"李小静",67),
  21. new Person(4,"李小静",67),
  22. new Person(4,"李小静",67),
  23. new Person(5,"罗泽成",12)
  24. );
  25.  
  26. public static void main(String[] args){
  27. tesst02();
  28. }
  29.  
  30. /**
  31. * sorted()方法,按照自然顺序排序
  32. */
  33. public static void tesst01(){
  34. List<String> list=Arrays.asList("bb","aa","dd","ee");
  35. list.stream()
  36. .sorted()
  37. .forEach(System.out::println);
  38.  
  39. }
  40.  
  41. /**
  42. * sorted(Comparator<? super T> comparator)方法,需要传一个比较器过去,按照指定的比较器进行排序
  43. */
  44. public static void tesst02(){
  45. list.stream().sorted((e1,e2)->{
  46. if(e1.age==e2.age){
  47. return e1.name.compareTo(e2.name);
  48. }else{
  49. return e1.age.compareTo(e2.age);
  50. }
  51. }).forEach(System.out::println);
  52.  
  53. }
  54.  
  55. }

步骤三:终止操作

终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、Integer,甚至是 void,终止操作也有多种

  1、查找与匹配

  

  1. package com.bjsxt.stream;
  2.  
  3. import com.bjsxt.Person;
  4.  
  5. import java.util.Arrays;
  6. import java.util.List;
  7. import java.util.Optional;
  8.  
  9. /**
  10. * stream
  11. * 终止操作
  12. */
  13. public class TestStream05 {
  14.  
  15. public static List<Person> list= Arrays.asList(
  16. new Person(1,"段然涛",18),
  17. new Person(2,"李飞宇",34),
  18. new Person(3,"卢晓倩",25),
  19. new Person(4,"李小静",67),
  20. new Person(4,"李小静",67),
  21. new Person(4,"李小静",67),
  22. new Person(5,"罗泽成",12)
  23. );
  24.  
  25. public static void main(String[] args){
  26. tesst01();
  27. }
  28.  
  29. /**
  30. * 终止操作
  31. * allMatch——检查是否匹配所有元素
  32. * anyMatch——检查是否至少匹配一个元素
  33. * noneMatch——检查是否没有匹配的元素
  34. * findFirst——返回第一个元素
  35. * findAny——返回当前流中的任意元素
  36. * count——返回流中元素的总个数
  37. * max——返回流中最大值
  38. * min——返回流中最小值
  39. */
  40. public static void tesst01(){
  41. boolean b1=list.stream().allMatch(person -> person.getAge()>10); //是否所有人的年龄大于10
  42. System.out.println(b1);
  43.  
  44. boolean b2=list.stream().anyMatch(person -> person.getAge()>100); //是否至少一个人的年龄大于100
  45. System.out.println(b2);
  46.  
  47. boolean b3=list.stream().noneMatch(person -> person.getAge()>100); //没有一个人的年龄大于100
  48. System.out.println(b3);
  49.  
  50. Optional<Person> optional=list.stream() //Optional是一个容器。java8新出的,防止空指针异常
  51. .findFirst(); //取第一个
  52. Person person=optional.get();
  53. System.out.println(person);
  54.  
  55. Optional<Person> optiona2=list.stream()
  56. .findAny(); //取任何一个
  57. Person person2=optional.get();
  58. System.out.println(person2);
  59.  
  60. Long ll=list.stream().count(); //个数
  61. System.out.println(ll);
  62.  
  63. Optional<Person> optiona3=list.stream().max((e1,e2)->{ // 取最大值,根据指定比较器
  64. if(e1.age==e2.age){
  65. return e1.name.compareTo(e2.name);
  66. }else{
  67. return e1.age.compareTo(e2.age);
  68. }
  69. });
  70. System.out.println(optiona3.get());
  71.  
  72. Optional<Person> optiona4=list.stream().min((e1,e2)->{ // 取最小值,根据指定比较器
  73. if(e1.age==e2.age){
  74. return e1.name.compareTo(e2.name);
  75. }else{
  76. return e1.age.compareTo(e2.age);
  77. }
  78. });
  79. System.out.println(optiona4.get());
  80.  
  81. }
  82.  
  83. }

  2、归约

  1. package com.bjsxt.stream;
  2.  
  3. import com.bjsxt.Person;
  4.  
  5. import java.util.*;
  6. import java.util.function.BinaryOperator;
  7. import java.util.stream.Collector;
  8. import java.util.stream.Collectors;
  9.  
  10. /**
  11. * stream
  12. * 终止操作
  13. */
  14. public class TestStream06 {
  15.  
  16. public static List<Person> list= Arrays.asList(
  17. new Person(1,"段然涛",18),
  18. new Person(2,"李飞宇",34),
  19. new Person(3,"卢晓倩",25),
  20. new Person(4,"李小静",67),
  21. new Person(4,"李小静",18),
  22. new Person(4,"李小静",67),
  23. new Person(5,"罗泽成",12)
  24. );
  25.  
  26. public static void main(String[] args){
  27. tesst01();
  28. }
  29.  
  30. /**
  31. *reduce()规约 可以将流中元素反复结合起来,得到一个值。返回 T
  32. */
  33. public static void tesst01(){
  34. List<Integer> list1=Arrays.asList(1,2,3,4,5,6,7,8,9,10);
  35. Integer integer=list1.stream().reduce(0, (x,y)->x+y); //0是起始值。然后0+1+2+3+4+5+...
  36. System.out.println(integer);
  37. System.out.println("---------------------------------------------");
  38.  
  39. Optional<Integer> optional=list.stream()
  40. .map(Person::getAge)
  41. .reduce(Integer::sum);
  42. System.out.println(optional.get());
  43. }

  3、收集

  1. package com.bjsxt.stream;
  2.  
  3. import com.bjsxt.Person;
  4.  
  5. import java.util.*;
  6. import java.util.function.BinaryOperator;
  7. import java.util.stream.Collector;
  8. import java.util.stream.Collectors;
  9.  
  10. /**
  11. * stream
  12. * 终止操作
  13. */
  14. public class TestStream06 {
  15.  
  16. public static List<Person> list= Arrays.asList(
  17. new Person(1,"段然涛",18),
  18. new Person(2,"李飞宇",34),
  19. new Person(3,"卢晓倩",25),
  20. new Person(4,"李小静",67),
  21. new Person(4,"李小静",18),
  22. new Person(4,"李小静",67),
  23. new Person(5,"罗泽成",12)
  24. );
  25.  
  26. public static void main(String[] args){
  27. tesst02();
  28. }/**
  29. * collect(Collector c)方法
  30. * 将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法
  31. * Collector 接口中方法的实现决定了如何对流执行收集操作(如收集到 List、Set、Map)。
  32. * 但是Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例
  33. */
  34. public static void tesst02(){
  35. //收集姓名放入list
  36. List<String> list2=list.stream()
  37. .map(Person::getName)
  38. .collect(Collectors.toList());
  39. list2.forEach(System.out::println);
  40.  
  41. System.out.println("--------------------------------------------");
  42.  
  43. //收集姓名放入set
  44. Set<String> set=list.stream()
  45. .map(Person::getName)
  46. .collect(Collectors.toSet());
  47. set.forEach(System.out::println);
  48.  
  49. System.out.println("--------------------------------------------");
  50.  
  51. //收集姓名放入指定的集合
  52. LinkedHashSet<String> linkedHashSet=list.stream()
  53. .map(Person::getName)
  54. .collect(Collectors.toCollection(LinkedHashSet::new));
  55. linkedHashSet.forEach(System.out::println);
  56.  
  57. System.out.println("--------------------------------------------");
  58.  
  59. //收集总个数
  60. Long count=list.stream()
  61. .collect(Collectors.counting());
  62. System.out.println(count);
  63.  
  64. System.out.println("--------------------------------------------");
  65.  
  66. //收集平均值
  67. Double integer=list.stream()
  68. .collect(Collectors.averagingDouble(Person::getAge));
  69. System.out.println(integer);
  70.  
  71. System.out.println("--------------------------------------------");
  72.  
  73. //收集总和
  74. Integer sum=list.stream()
  75. .collect(Collectors.summingInt(Person::getAge));
  76. System.out.println(sum);
  77.  
  78. System.out.println("--------------------------------------------");
  79.  
  80. //收集最大值
  81. Optional<Person> optional=list.stream()
  82. .collect(Collectors.maxBy((p1,p2)->Integer.compare(p1.getAge(),p2.getAge())));
  83. System.out.println(optional.get());
  84.  
  85. System.out.println("--------------------------------------------");
  86.  
  87. //收集最小值
  88. Optional<Person> optional2=list.stream()
  89. .collect(Collectors.maxBy((p1,p2)->-Integer.compare(p1.getAge(),p2.getAge())));
  90. System.out.println(optional2.get());
  91.  
  92. System.out.println("--------------------------------------------");
  93.  
  94. //分组,名字相同的分为一组
  95. Map<String,List<Person>> map=list.stream()
  96. .collect(Collectors.groupingBy(Person::getName));
  97. System.out.println(map);
  98.  
  99. System.out.println("--------------------------------------------");
  100.  
  101. //分组,名字相同的分为一组,名字相同再根据年龄分组
  102. Map<String,Map<String,List<Person>>> map1=list.stream()
  103. .collect(Collectors.groupingBy(Person::getName,Collectors.groupingBy((p)->{
  104. if(p.getAge()>20){
  105. return "青年";
  106. }else{
  107. return "老年";
  108. }
  109. })));
  110. System.out.println(map1);
  111.  
  112. System.out.println("--------------------------------------------");
  113.  
  114. //分区,只能分为两个区,true和false两个区,根据年龄40分为两个区
  115. Map<Boolean,List<Person>> map2=list.stream()
  116. .collect(Collectors.partitioningBy((e)->e.getAge()>40));
  117. System.out.println(map2);
  118.  
  119. System.out.println("--------------------------------------------");
  120.  
  121. //求总和。平均值。总数、最大值、最小值等等
  122. DoubleSummaryStatistics dss= list.stream()
  123. .collect(Collectors.summarizingDouble(Person::getAge));
  124. System.out.println(dss.getSum());
  125. System.out.println(dss.getAverage());
  126. System.out.println(dss.getCount());
  127.  
  128. System.out.println("--------------------------------------------");
  129.  
  130. //把姓名按照“,”分割
  131. String str=list.stream()
  132. .map(Person::getName)
  133. .collect(Collectors.joining(","));
  134. System.out.println(str);
  135.  
  136. System.out.println("--------------------------------------------");
  137. }
  138.  
  139. }

七:并行流和串行流

并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。Java 8 中将并行进行了优化,我们可以很容易的对数据进行并行操作。Stream API 可以声明性地通过 parallel() 与sequential() 在并行流与顺序流之间进行切换。java8中的并行流底层就是采用的java的Fork/Join 框架

  1. package com.bjsxt.forkJoin;
  2.  
  3. import java.time.Duration;
  4. import java.time.Instant;
  5. import java.util.concurrent.ForkJoinPool;
  6. import java.util.stream.LongStream;
  7.  
  8. /**
  9. * Created by Administrator on 2019/3/7.
  10. */
  11. public class TestForkJoin {
  12.  
  13. public static void main(String[] args){
  14. test02();
  15. }
  16.  
  17. public static void test02(){
  18. long start = System.currentTimeMillis();
  19. Long sum = LongStream.rangeClosed(0L, 10000000000L)
  20. .parallel()  //切换到并行流
  21. .sum();
  22. System.out.println(sum);
  23. long end = System.currentTimeMillis();
  24. System.out.println("耗费的时间为: " + (end - start));
  25. }
  26. }

这里有必要简单介绍下Fork/Join框架

Fork/Join 框架:就是在必要的情况下,将一个大任务,进行拆分(fork)成若干个小任务(拆到不可再拆时),再将一个个的小任务运算的结果进行 join 汇总

Fork/Join 框架与传统线程池的区别
采用 “工作窃取”模式(work-stealing):
当执行新的任务时它可以将其拆分分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中。相对于一般的线程池实现,fork/join框架的优势体现在对其中包含的任务的处理方式上.在一般的线程池中,如果一个线程正在执行的任务由于某些原因无法继续运行,那么该线程会处于等待状态.而在fork/join框架实现中,如果某个子问题由于等待另外一个子问题的完成而无法继续运行.那么处理该子问题的线程会主动寻找其他尚未运行的子问题来执行.这种方式减少了线程的等待时间,提高了性能

案例:计算start与end之间的值的总和

  1. package com.bjsxt.forkJoin;
  2.  
  3. import java.util.concurrent.RecursiveTask;
  4.  
  5. /**
  6. * 计算start与end之间的值的总和
  7. */
  8. public class ForkJoinCalculate extends RecursiveTask<Long> {
  9.  
  10. private long start;
  11.  
  12. private long end;
  13.  
  14. private static final long THRESHOLD = 100000L; //临界值
  15.  
  16. public ForkJoinCalculate(long start, long end) {
  17. this.start = start;
  18. this.end = end;
  19. }
  20.  
  21. /**
  22. *
  23. * @return
  24. */
  25. @Override
  26. protected Long compute() {
  27. long length=end-start;
  28. if(length<THRESHOLD){ //已经小于临界值
  29. long sum=0;
  30. for(long i=start;i<=end;i++){
  31. sum+=sum+i;
  32. }
  33. return sum;
  34. }else{ //没到临界值,需要继续分割任务
  35. long middle=(start+end)/2;
  36. ForkJoinCalculate left=new ForkJoinCalculate(start,middle);
  37. left.fork();
  38. ForkJoinCalculate right=new ForkJoinCalculate(middle+1,end);
  39. right.fork();
  40. return left.join()+right.join();
  41. }
  42. }
  43. }
  1. package com.bjsxt.forkJoin;
  2.  
  3. import java.time.Duration;
  4. import java.time.Instant;
  5. import java.util.concurrent.ForkJoinPool;
  6. import java.util.stream.LongStream;
  7.  
  8. /**
  9. * Created by Administrator on 2019/3/7.
  10. */
  11. public class TestForkJoin {
  12.  
  13. public static void main(String[] args){
  14. test01();
  15. }
  16.  
  17. public static void test01(){
  18. Instant strat=Instant.now();
  19. ForkJoinPool forkJoinPool=new ForkJoinPool();
  20. ForkJoinCalculate forkJoinCalculate=new ForkJoinCalculate(0,100000000000L);
  21. long sum=forkJoinPool.invoke(forkJoinCalculate);
  22. System.out.println(sum);
  23. Instant end=Instant.now();
  24. System.out.println("计算耗时:"+ Duration.between(strat,end).toMillis());
  25. }
  26.  
  27. }

八、Optional 类

Optional<T> 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且可以避免空指针异常

  1. package com.bjsxt.optiona;
  2.  
  3. import com.bjsxt.Person;
  4.  
  5. import java.util.Optional;
  6.  
  7. /**
  8. * 一、Optional 容器类:用于尽量避免空指针异常
  9. * Optional.of(T t) : 创建一个 Optional 实例
  10. * Optional.empty() : 创建一个空的 Optional 实例
  11. * Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例
  12. * isPresent() : 判断是否包含值
  13. * orElse(T t) : 如果调用对象包含值,返回该值,否则返回t
  14. * orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值
  15. * map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
  16. * flatMap(Function mapper):与 map 类似,要求返回值必须是Optional
  17. */
  18. public class TestOptiona {
  19.  
  20. public static void main(String[] args){
  21. test01();
  22. }
  23.  
  24. public static void test01(){
  25. Optional<Person> optional=Optional.of(new Person()); //如果of()方法里面的值为null,下面一句会发生空指针异常
  26. Person p=optional.get(); //获取Optional容器中的值
  27. System.out.println(p);
  28. }
  29.  
  30. public static void test02(){
  31. Optional<Person> optional=Optional.empty(); //创建一个空的 Optional 实例
  32. Optional<Person> optiona2=Optional.ofNullable(new Person());//若 参数 不为 null,创建 Optional 实例,否则创建空实例
  33. }
  34.  
  35. public static void test03(){
  36. Optional<Person> optiona2=Optional.ofNullable(new Person());//若 参数 不为 null,创建 Optional 实例,否则创建空实例
  37. if(optiona2.isPresent()){ //判断Optional容器中是否包含值
  38. System.out.println("有值。。。");
  39. }
  40.  
  41. Person p1 = optiona2.orElse(new Person(1,"张三",23)); //如果容器值为空,则值为orElse()方法的参数
  42. System.out.println(p1);
  43.  
  44. Person p2 = optiona2.orElseGet(() -> new Person()); //同orElse(),只不过参数是一个函数式接口
  45. System.out.println(p2);
  46. }
  47.  
  48. public void test04(){
  49. Optional<Person> op = Optional.of(new Person(1,"张三",23));
  50.  
  51. Optional<String> op2 = op.map(Person::getName);
  52. System.out.println(op2.get());
  53.  
  54. Optional<String> op3 = op.flatMap((e) -> Optional.of(e.getName()));
  55. System.out.println(op3.get());
  56. }
  57.  
  58. }

9、新的时间与日期API

java之前的时间对象是可变的对象,存在线程安全问题,java8引入了全新的时间类

LocalDate、LocalTime、LocalDateTime 类的实例是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。它们提供了简单的日期或时间,并不包含当前的时间信息。也不包含与时区相关的信息。

Instant 时间戳,用于“时间戳”的运算。它是以Unix元年(传统的设定为UTC时区1970年1月1日午夜时分)开始所经历的描述进行运算

Duration:用于计算两个“时间”间隔

Period:用于计算两个“日期”间隔

TemporalAdjuster : 时间校正器。有时我们可能需要获取例如:将日期调整到“下个周日”等操作。

TemporalAdjusters : 该类通过静态方法提供了大量的常用 TemporalAdjuster 的实现。

java.time.format.DateTimeFormatter 类:该类提供了三种
格式化方法:
  预定义的标准格式
  语言环境相关的格式
  自定义的格式

java8新特性学习2的更多相关文章

  1. Java8 新特性学习 Lambda表达式 和 Stream 用法案例

    Java8 新特性学习 Lambda表达式 和 Stream 用法案例 学习参考文章: https://www.cnblogs.com/coprince/p/8692972.html 1.使用lamb ...

  2. java8 新特性学习笔记

    Java8新特性 学习笔记 1主要内容 Lambda 表达式 函数式接口 方法引用与构造器引用 Stream API 接口中的默认方法与静态方法 新时间日期 API 其他新特性 2 简洁 速度更快 修 ...

  3. java8新特性学习:函数式接口

    本文概要 什么是函数式接口? 如何定义函数式接口? 常用的函数式接口 函数式接口语法注意事项 总结 1. 什么是函数式接口? 函数式接口其实本质上还是一个接口,但是它是一种特殊的接口:SAM类型的接口 ...

  4. java8新特性学习1

    java8增加了不少新特性,下面就一些常见的新特性进行学习... 1.接口中的方法 2.函数式接口 3.Lambda表达式 4.java8内置的四大核心函数式接口 5.方法引用和构造器引用 6.Str ...

  5. java8新特性学习:stream与lambda

    Streams api 对 Stream 的使用就是实现一个 filter-map-reduce 过程,产生一个最终结果,或者导致一个副作用(side effect). 流的操作类型分为两种: Int ...

  6. Java8 新特性学习

    摘自:https://blog.csdn.net/shuaicihai/article/details/72615495 Lambda 表达式 Lambda 是一个匿名函数,我们可以把 Lambda ...

  7. java8新特性学习笔记(二) 使用流(各种API)

    筛选和切片 用谓词筛选,筛选出各个不相同的元素,忽略流中的头几个元素,或将流截断至指定长度 用谓词筛选 Stream接口支持filter方法,该操作接受一个谓词(返回一个boolean的函数) 作为参 ...

  8. java8新特性学习笔记(二) 流的相关思想

    流是什么 流是Java API的新成员,他允许你以声明的方式处理数据集合,就现在来说,可以把他们看成遍历数据集合的高级迭代器.此外,流还可以透明地并行处理,你无须写任何多线程代码. 下面例子是新老AP ...

  9. Java8新特性学习笔记(一) Lambda表达式

    没有用Lambda表达式的写法: Comparator<Transaction> byYear = new Comparator<Transaction>() { @Overr ...

随机推荐

  1. 检测SQL Server表占用空间大小SQL

    检测SQL Server表占用空间大小SQL,要先选择需要查询的数据库,然后点击执行下面脚本. ),ROWS ),reserved ) ,Data ) ,index_size ) ,Unused ) ...

  2. JavaScript typeof运算符和数据类型

    // js有6种数据类型:Undefined.Null.Boolean.String.Number.Object //(01)typeof console.log(typeof undefined); ...

  3. 使用python简单创建一个用户和商城小程序

    整体思路: 1.用户功能:购买.显示余额.列表清单.输入 2.商家功能:修改和添加商品 创建两个接口: 用户: #Author: Gordon #读取文档,生成goodsf = open('goods ...

  4. Django之(URL)路由系统

    路由系统 简而言之,django的路由系统作用就是使views里面处理数据的函数与请求的url建立映射关系.使请求到来之后,根据urls.py里的关系条目,去查找到与请求对应的处理方法,从而返回给客户 ...

  5. Maven学习篇一:eclipse构建运行maven web项目

    1.new->other->maven project->next 2.选择创建简单项目(或者直接去掉勾,在后面选择maven-archetype-webapp) 3.设置坐标,名称 ...

  6. 【代码笔记】Java基础:Java的方法和类

    面向过程与面向对象都是我们编程中,编写程序的一种思维方式.例如:公司打扫卫生(擦玻璃.扫地.拖地.倒垃圾等), 按照面向过程的程序设计方式会思考“打扫卫生我该怎么做,然后一件件的完成”,最后把公司卫生 ...

  7. github使用手册

    1.git init 2.git add README.md (增加文件夹/文件:git add dir/files) 3.git commit -m "注释内容” 4.git push - ...

  8. 纯css 简单网页

    <div id="wrapper"> <header> <section> <h1>Web Design<h1> < ...

  9. ArcGIS软件操作——地图制图

    ArcGIS软件操作系列二(地图制图) 2016年毕业,参加工作,除了平时出差,大部分时间都在使用ArcGIS处理数据.制图,在此,先将一些制图的小心得撰写出来,希望能与各位共同交流. 1 数据准备: ...

  10. 关于 document.compatMode

    今天查资料时无意发现一个以前没有注意到过的属性:document.compatMode 经过一番资料的查询后,了解到以下信息: 我们都知道IE有两种盒子模型,在不声明 !DOCTYPE 时是混杂模式 ...