为啥放着Java16不用都在用java8?看完这个你就知道了

Dear 丶 2021-09-25 06:00 353阅读 0赞

函数式接口

java内置四大核心函数式接口
image.png
核心接口子接口
image.png

  1. //Consumer<T>消费型接口
  2. public static void test1(){
  3. cost(8888, (m) -> System.out.println("共消费:" + m + "元"));
  4. }
  5. public static void cost(double money,Consumer<Double> con){
  6. con.accept(money);
  7. }
  8. //Supplier<T> 供给型接口
  9. public static void test2(){
  10. List<Integer> list = getNumList(8, () -> (int)(Math.random() * 100));
  11. for (Integer integer : list) {
  12. System.out.println(integer);
  13. }
  14. }
  15. //产生指定数量的整数,放入集合中
  16. public static List<Integer> getNumList(int num,Supplier<Integer> sup){
  17. List<Integer> list = new ArrayList<>();
  18. for (int i = 0; i < num; i++) {
  19. Integer n = sup.get();
  20. list.add(n);
  21. }
  22. return list;
  23. }
  24. //Function<T,R> 函数型接口
  25. public static void test3(){
  26. String string = strHandler("函数型接口测试 ", (str) -> str.trim().substring(0, 5));
  27. System.out.println(string);
  28. }
  29. //用于处理字符串
  30. public static String strHandler(String str,Function<String, String> fun){
  31. return fun.apply(str);
  32. }
  33. //Predicate<T> 断言型接口
  34. public static void test4(){
  35. List<String> list = Arrays.asList("hello","Lambda","ok");
  36. List<String> strList = filterStr(list, (s) -> s.length() > 3);
  37. for (String string : strList) {
  38. System.out.println(string);
  39. }
  40. }
  41. //将满足条件的字符串,放入集合中
  42. public static List<String> filterStr(List<String> list, Predicate<String> pre){
  43. List<String> strList = new ArrayList<>();
  44. for (String str : list) {
  45. if (pre.test(str)) {
  46. strList.add(str);
  47. }
  48. }
  49. return strList;
  50. }

方法引用与构造器引用

当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!(实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!)方法引用:使用操作符 “::” 将方法名和对象或类的名字分隔开来。
如下三种主要使用情况:

  • 对象::实例方法
  • 类::静态方法
  • 类::实例方法

使用注意事项:

1.Lambda 体中调用方法的参数列表与返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致。
2.若Lambda 参数列表中第一个参数是实例方法调用者,第二个参数是实例方法的参数 可以使用 ClassName :: method

  1. //对象的引用 :: 实例方法名
  2. @Test
  3. public void test1(){
  4. PrintStream ps = System.out;
  5. Consumer<String> con = (str) -> ps.println(str);
  6. con.accept("Hello World!");
  7. Consumer<String> con2 = ps::println;
  8. con2.accept("Hello World!");
  9. Consumer<String> con3 = System.out::println;
  10. }
  11. //类名 :: 静态方法名
  12. @Test
  13. public void test2(){
  14. Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
  15. Comparator<Integer> com2 = Integer::compare;
  16. }
  17. //类名 :: 实例方法名
  18. @Test
  19. public void test3(){
  20. BiPredicate<String, String> bp = (x, y) -> x.equals(y);
  21. System.out.println(bp.test("abcde", "abcde"));
  22. BiPredicate<String, String> bp2 = String::equals;
  23. System.out.println(bp2.test("abc", "abc"));
  24. Function<Employee, String> fun = (e) -> e.show();
  25. System.out.println(fun.apply(new Employee()));
  26. Function<Employee, String> fun2 = Employee::show;
  27. System.out.println(fun2.apply(new Employee()));
  28. }

构造器引用:

  • 构造器参数列表要与接口中抽象方法的参数列表一致,格式为 类名::new
  • 与函数式接口相结合,自动与函数式接口中方法兼容

    public void test1(){

    1. Supplier<Employee> sup = () -> new Employee();
    2. System.out.println(sup.get());
    3. Supplier<Employee> sup1 = Employee::new;
    4. System.out.println(sup1.get());
    5. }

数组引用

  • 格式:类型[] :: new

    public void test1(){

    1. Function<Integer, String[]> fun = (args) -> new String[args];
    2. String[] strs = fun.apply(10);
    3. System.out.println(strs.length);
    4. Function<Integer, String[]> fun1 = String[] :: new;
    5. String[] strs = fun1.apply(20);
    6. System.out.println(strs.length);
    7. }

Stream API

Stream 是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列Stream 自己不会存储元素,不会改变源对象且返回一个持有结果的新Stream,操作是延迟执行的Stream API 提供了一种高效且易于使用的处理数据的方式

Stream API 的操作步骤:

1.创建Stream数据源
2.中间操作
3.终止操作(终端操作)

创建Stream

  • 方式一:Java8中的Collection接口被扩展.提供两个获取流的方法

default Stream stream() : 返回一个顺序流

default Stream parallelStream() : 返回一个并行流

注:Collection接口下的所有实现类或者子接口都可以通过 对象.stream() 的方法返回一个流给Stream对象

  • 方式二:Java8中的Arrays的静态方法 stream() 可以获取数组流

static Stream stream(T[] array)

注:从数组中获取流可以使用 Arrays.stream(数组名) 来进行获取

  • 方式三:Stream类的静态方法 Stream.of() 通过显示值创建一个流,可接收任意数量的参数

public static Stream of(T… values) : 返回一个流

使用 Stream stream = Stream.of(“a”,“b”,“c”) 获取流

  • 方式四:静态方法 Stream.iterate() 和 Stream.generate() 创建无限流

迭代 public static Stream iterate(final T seed, final UnaryOperator f)

生成 public static Stream generate(Supplier s)

  1. public void test1(){
  2. //1.可以通过Collection系列集合提供的stream() 或parallelStream()
  3. List<String> list = new ArrayList<>();
  4. Stream<String> stream = list.stream();
  5. //2.通过Arrays中静态方法 stream() 获取数组流
  6. Person[] persons = new Person[10];
  7. Stream<Person> stream2 = Arrays.stream(persons);
  8. //3.通过Stream类中的静态方法 of()
  9. Stream<String> stream3 = Stream.of("a","b","c");
  10. //4.创建无限流
  11. //迭代
  12. Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);
  13. stream4.limit(8).forEach(System.out :: println);
  14. //生成
  15. Stream.generate(() -> Math.random()).limit(6)
  16. .forEach(System.out :: println);
  17. }

中间操作

筛选与切片方法

  • filter(Perticate p) — 接收 Lambda , 从流中排除某些元素
  • distinct() — 筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
  • limit(Long n) — 截断流,使其元素不超过给定数量
  • skip(Long n) —— 跳过元素,返回一个扔掉了前 n 个元素的流,若流中元素不足 n 个,则返回一个空流,与 limit(n) 互补

映射方法

  • map(Function f) — 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
  • flatMap(Function f) — 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
  • mapToDouble(ToDoubleFunction f) — 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 DoubleStream
  • mapToInt(ToIntFunction f) — 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的IntStream
  • mapToLong(ToLongFunction f) — 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的LongStream

排序方法

  • sorted() — 产生一个新流,按自然顺序排序
  • sorted(Comparator com) — 产生一个新流,按比较器顺序定制排序

    /* Stream API的中间操作 */

    1. public class TestSteamAPI2 {
    2. List<Person> persons = Arrays.asList(
    3. new Person(2, "钱四", 24),
    4. new Person(1, "张三", 33),
    5. new Person(2, "李四", 24),
    6. new Person(3, "王五", 65),
    7. new Person(4, "赵六", 26),
    8. new Person(4, "赵六", 26),
    9. new Person(5, "陈七", 27)
    10. );
    11. //内部迭代,由Stream API完成
    12. @Test
    13. public void test1(){
    14. //中间操作,不会执行任何操作
    15. Stream<Person> stream = persons.stream()
    16. .filter((e) -> {
    17. System.out.println("Stream的中间操作");
    18. return e.getAge() > 25;
    19. });
    20. //终止操作,一次性执行全部内容,即"惰性求值"
    21. stream.forEach(System.out :: println);
    22. }
    23. //外部迭代
    24. @Test
    25. public void test2(){
    26. Iterator<Person> iterator = persons.iterator();
    27. while (iterator.hasNext()) {
    28. System.out.println(iterator.next());
    29. }
    30. }
    31. //limit,截断
    32. @Test
    33. public void test3(){
    34. persons.stream()
    35. .filter((e) -> {
    36. System.out.println("迭代操作"); //短路
    37. return e.getAge() > 24;
    38. })
    39. .limit(2)
    40. .forEach(System.out :: println);
    41. }
    42. //跳过skip,distinct去重(要重写equals和hashcode)
    43. @Test
    44. public void test4(){
    45. persons.stream()
    46. .filter((e) -> e.getAge() > 23)
    47. .skip(2)
    48. .distinct()
    49. .forEach(System.out :: println);
    50. }
    51. //映射
    52. @Test
    53. public void test5(){
    54. List<String> list = Arrays.asList("a","bb","c","d","e");
    55. list.stream().map((str) -> str.toUpperCase())
    56. .forEach(System.out :: println);
    57. System.out.println("---------------");
    58. persons.stream().map((Person :: getName)).forEach(System.out :: println);
    59. System.out.println("---------------");
    60. Stream<Stream<Character>> stream = list.stream()
    61. .map(TestSteamAPI2 :: filterCharacter);
    62. stream.forEach((s) -> {
    63. s.forEach(System.out :: println);
    64. });
    65. System.out.println("-----------------");
    66. //flatMap
    67. Stream<Character> stream2 = list.stream()
    68. .flatMap(TestSteamAPI2 :: filterCharacter);
    69. stream2.forEach(System.out :: println);
    70. }
    71. //处理字符串
    72. public static Stream<Character> filterCharacter(String str){
    73. List<Character> list = new ArrayList<>();
    74. for (Character character : str.toCharArray()) {
    75. list.add(character);
    76. }
    77. return list.stream();
    78. }
    79. //排序
    80. @Test
    81. public void test6(){
    82. List<String> list = Arrays.asList("bb","c","aa","ee","ddd");
    83. list.stream()
    84. .sorted() //自然排序
    85. .forEach(System.out :: println);
    86. System.out.println("------------");
    87. persons.stream()
    88. .sorted((p1,p2) -> {
    89. if (p1.getAge() == p2.getAge()) {
    90. return p1.getName().compareTo(p2.getName());
    91. } else {
    92. return p1.getAge() - p2.getAge();
    93. }
    94. }).forEach(System.out :: println);
    95. }
    96. }

终止操作

查找与匹配方法

  • allMatch(Perticate p) — 检查是否匹配所有元素
  • anyMatch(Perticate p) — 检查是否至少匹配一个元素
  • noneMatch(Perticate p) — 检查是否没有匹配的元素
  • findFirst() — 返回第一个元素
  • findAny() — 返回当前流中的任意元素
  • count() — 返回流中元素的总个数
  • max(Comparator c) — 返回流中最大值
  • min(Comparator c) — 返回流中最小值
  • forEach(Consumer c) — 内部迭代(使用Collection接口需用户做迭代成为外部迭代)

归约方法

  • reduce(T identity, BinaryOperator b) — 可以将流中元素反复结合起来,得到一个值返回T
  • reduce(BinaryOperator b) — 可以将流中元素反复结合起来,得到一个值,返回Optional

收集方法

collect(Collector c)——将流转换为其他形式,接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法

  1. /** * Stream API的终止操作 */
  2. public class TestSteamAPI3 {
  3. List<Person> persons = Arrays.asList(
  4. new Person(2, "钱四", 24,Status.YOUNG),
  5. new Person(1, "张三", 23,Status.YOUNG),
  6. new Person(2, "李四", 24,Status.YOUNG),
  7. new Person(3, "王五", 65,Status.OLD),
  8. new Person(4, "赵六", 26,Status.MIDDLE),
  9. new Person(4, "赵六", 56,Status.OLD),
  10. new Person(5, "陈七", 27,Status.MIDDLE)
  11. );
  12. //查找与匹配
  13. @Test
  14. public void test1(){
  15. boolean b = persons.stream()
  16. .allMatch((e) -> e.getStatus().equals(Status.YOUNG));
  17. System.out.println(b);
  18. boolean b2 = persons.stream()
  19. .anyMatch((e) -> e.getStatus().equals(Status.YOUNG));
  20. System.out.println(b2);
  21. boolean b3 = persons.stream()
  22. .noneMatch((e) -> e.getStatus().equals(Status.MIDDLE));
  23. System.out.println(b3);
  24. Optional<Person> op = persons.stream()
  25. .sorted((e1,e2) -> Integer.compare(e1.getAge(), e2.getAge()))
  26. .findFirst();
  27. System.out.println(op.get());
  28. Optional<Person> optional = persons.stream()
  29. .filter((e) -> e.getStatus().equals(Status.OLD))
  30. .findAny();
  31. System.out.println(optional.get());
  32. }
  33. //最大,最小
  34. @Test
  35. public void test2(){
  36. long count = persons.stream()
  37. .count();
  38. System.out.println(count);
  39. Optional<Person> optional = persons.stream()
  40. .max((e1,e2) -> Integer.compare(e1.getId(), e2.getId()));
  41. System.out.println(optional.get());
  42. Optional<Integer> op = persons.stream()
  43. .map(Person :: getAge)
  44. .min(Integer :: compare);
  45. System.out.println(op.get());
  46. }
  47. //归约
  48. @Test
  49. public void test3(){
  50. List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8);
  51. Integer sum = list.stream()
  52. .reduce(0, (x,y) -> x + y);
  53. System.out.println(sum);
  54. System.out.println("------------");
  55. Optional<Integer> optional = persons.stream()
  56. .map(Person :: getAge)
  57. .reduce(Integer :: sum);
  58. System.out.println(optional.get());
  59. }
  60. //收集
  61. @Test
  62. public void test4(){
  63. List<String> list = persons.stream()
  64. .map(Person :: getName)
  65. .collect(Collectors.toList());
  66. list.forEach(System.out :: println);
  67. System.out.println("------------");
  68. Set<String> set = persons.stream()
  69. .map(Person :: getName)
  70. .collect(Collectors.toSet());
  71. set.forEach(System.out :: println);
  72. System.out.println("------------");
  73. HashSet<String> hashSet = persons.stream()
  74. .map(Person :: getName)
  75. .collect(Collectors.toCollection(HashSet :: new));
  76. hashSet.forEach(System.out :: println);
  77. }
  78. @Test
  79. public void test5(){
  80. Long count = persons.stream()
  81. .collect(Collectors.counting());
  82. System.out.println("总人数="+count);
  83. System.out.println("----------------");
  84. //平均值
  85. Double avg = persons.stream()
  86. .collect(Collectors.averagingInt(Person :: getAge));
  87. System.out.println("平均年龄="+avg);
  88. System.out.println("---------------");
  89. //总和
  90. Integer sum = persons.stream()
  91. .collect(Collectors.summingInt(Person :: getAge));
  92. System.out.println("年龄总和="+sum);
  93. System.out.println("----------------");
  94. //最大值
  95. Optional<Person> max = persons.stream()
  96. .collect(Collectors.maxBy((e1,e2) -> Integer.compare(e1.getAge(), e2.getAge())));
  97. System.out.println("最大年龄是"+max.get());
  98. System.out.println("----------------");
  99. //最小值
  100. Optional<Person> min = persons.stream()
  101. .collect(Collectors.minBy((e1,e2) -> Integer.compare(e1.getAge(), e2.getAge())));
  102. System.out.println("最小年龄是"+min.get());
  103. }
  104. //分组
  105. @Test
  106. public void test6(){
  107. Map<Status, List<Person>> map = persons.stream()
  108. .collect(Collectors.groupingBy(Person :: getStatus));//根据年龄层分组
  109. System.out.println(map);
  110. }
  111. //多级分组
  112. @Test
  113. public void test7(){
  114. Map<Status, Map<String, List<Person>>> map = persons.stream()
  115. .collect(Collectors.groupingBy(Person :: getStatus ,Collectors.groupingBy((e) -> {
  116. if (e.getId()%2 == 1) {
  117. return "单号";
  118. } else {
  119. return "双号";
  120. }
  121. })));
  122. System.out.println(map);
  123. }
  124. //分区
  125. @Test
  126. public void test8(){
  127. Map<Boolean, List<Person>> map = persons.stream()
  128. .collect(Collectors.partitioningBy((e) -> e.getAge() > 30));
  129. System.out.println(map);
  130. }
  131. //IntSummaryStatistics
  132. @Test
  133. public void test9(){
  134. IntSummaryStatistics iss = persons.stream()
  135. .collect(Collectors.summarizingInt(Person :: getAge));
  136. System.out.println(iss.getSum());
  137. System.out.println(iss.getAverage());
  138. System.out.println(iss.getMax());
  139. }
  140. @Test
  141. public void test10(){
  142. String str = persons.stream()
  143. .map(Person :: getName)
  144. .collect(Collectors.joining(",","人员名单:","等"));
  145. System.out.println(str);
  146. }
  147. }

并行流与串行

为了适应目前多核机器的时代,提高系统CPU、内存的利用率,在jdk1.8新的stream包中针对集合的操作也提供了并行操作流和串行操作流。并行流就是把内容切割成多个数据块,并且使用多个线程分别处理每个数据块的内容。Stream api中声明可以通过parallel()与sequential()方法在并行流和串行流之间进行切换,jdk1.8并行流使用的是fork/join框架进行并行操作
注:使用并行流并不是一定会提高效率,因为jvm对数据进行切片和切换线程也是需要时间的。所以数据量越小,串行操作越快;数据量越大,并行操作效果越好

  1. /* FrokJoin框架 */
  2. public class ForkJoinCalculate extends RecursiveTask<Long>{
  3. private static final long serialVersionUID = 1L;
  4. private long start;
  5. private long end;
  6. private static final long THRESHOLD = 10000;
  7. public ForkJoinCalculate() {
  8. }
  9. public ForkJoinCalculate(long start, long end) {
  10. this.start = start;
  11. this.end = end;
  12. }
  13. @Override
  14. protected Long compute() {
  15. long length = end - start ;
  16. if (length <= THRESHOLD) {
  17. long sum = 0;
  18. for (long i = start; i <= end; i++) {
  19. sum += i;
  20. }
  21. return sum;
  22. }else {
  23. long middle = (start + end) / 2;
  24. ForkJoinCalculate left = new ForkJoinCalculate();
  25. left.fork();//拆分子任务,同时压入线程队列
  26. ForkJoinCalculate right = new ForkJoinCalculate();
  27. right.fork();
  28. return left.join() + right.join();
  29. }
  30. }
  31. }
  32. public class TestForkJoin {
  33. /** * FrokJoin框架 */
  34. @Test
  35. public void test1(){
  36. Instant start = Instant.now();
  37. ForkJoinPool pool = new ForkJoinPool();
  38. ForkJoinTask<Long> task = new ForkJoinCalculate(0,10000000000L);
  39. Long sum = pool.invoke(task);
  40. System.out.println(sum);
  41. Instant end = Instant.now();
  42. System.out.println(Duration.between(start,end).toMillis());
  43. }
  44. /** * for循环 */
  45. @Test
  46. public void test2(){
  47. Instant start = Instant.now();
  48. long sum = 0L;
  49. for (long i = 0; i <= 10000000000L; i++) {
  50. sum += i;
  51. }
  52. System.out.println(sum);
  53. Instant end = Instant.now();
  54. System.out.println(Duration.between(start, end).toMillis());
  55. }
  56. /** * Java8并行流 */
  57. @Test
  58. public void test3(){
  59. Instant start = Instant.now();
  60. LongStream.rangeClosed(0, 10000000000L)
  61. .parallel()
  62. .reduce(0,Long :: sum);
  63. Instant end = Instant.now();
  64. System.out.println(Duration.between(start, end).toMillis());
  65. }
  66. }

接口中的默认方法与静态方法

  1. //jdk1.8以前接口中的变量必须是public static final的,方法也必须是public的,所以下面的定义是等价的
  2. public interface MyService {
  3. public static final String KEY = "hello world";
  4. String key = "hello world";
  5. public abstract void sayHello();
  6. void sayHi();
  7. }
  8. //但是从jdk1.8开始,这种现象有了改变,jdk添加了接口的默认方法和静态方法,使用如下方式定义
  9. public interface MyService {
  10. /* 静态方法 */
  11. static void method1(){
  12. System.out.println("这个是静态方法,调用方式为:MyService.method1()");
  13. }
  14. /* 默认方法 */
  15. default void method2(){
  16. System.out.println("这个是默认方法,调用方式为MyService实例.method2()");
  17. }
  18. }

注:由于Java支持一个实现类可以实现多个接口,如果多个接口中存在同样的static和default方法会怎么样呢?
如果有两个接口中的静态方法一模一样,并且一个实现类同时实现了这两个接口,此时并不会产生错误,因为jdk8只能通过接口类调用接口中的静态方法,所以对编译器来说是可以区分的。但是如果两个接口中定义了一模一样的默认方法,并且一个实现类同时实现了这两个接口,那么必须在实现类中重写默认方法,否则编译失败

新时间日期API

原有日期api的缺点

  • 从jdk1.1开始创建,日期处理没有规范,处于多个包中比如:java.util.Date,java.text.java.text.DateFormat等
  • 现有的日期api存在多线程的线程安全问题(可通过比如ThreadLocal等方式规避)

新日期api简介

优势新日期api是线程安全的,统一放在java.time及其子包中,关注点分离,对于机器使用的时间戳和人可读的日期进行了类的分类

java.time及其子包说明

  • java.time包:这是新的Java日期/时间API的基础包,所有的主要基础类都是这个包的一部分,如:LocalDate, LocalTime, LocalDateTime, Instant, Period, Duration等等。所有这些类都是不可变的和线程安全的,在绝大多数情况下,这些类能够有效地处理一些公共的需求
  • java.time.chrono包:这个包为非ISO的日历系统定义了一些泛化的API,我们可以扩展AbstractChronology类来创建自己的日历系统
  • java.time.format包:这个包包含能够格式化和解析日期时间对象的类,在绝大多数情况下,我们不应该直接使用它们,因为java.time包中相应的类已经提供了格式化和解析的方法
  • java.time.temporal包:这个包包含一些时态对象,我们可以用其找出关于日期/时间对象的某个特定日期或时间,比如说,可以找到某月的第一天或最后一天。你可以非常容易地认出这些方法,因为它们都具有“withXXX”的格式
  • java.time.zone包:这个包包含支持不同时区以及相关规则的类
  1. public class LocalDateTimeTest {
  2. /* localDate/localtime/localdateTime */
  3. @Test
  4. public void test1(){
  5. //获取当前日期时间
  6. LocalDateTime ldt = LocalDateTime.now();
  7. System.out.println(ldt);
  8. //按照指定时间生成日期
  9. LocalDateTime ldt1 = LocalDateTime.of(2020,12,30,1,2,3);
  10. System.out.println(ldt1);
  11. //指定时间+2年
  12. System.out.println(ldt.plusYears(2));
  13. //指定时间-3月
  14. LocalDateTime ldt2 = ldt.minusMonths(3);
  15. System.out.println(ldt2);
  16. System.out.println(ldt.getYear());//获取年份
  17. System.out.println(LocalDate.now());//获取日期
  18. }
  19. /* 时间戳 (使用Unix元年 1970年1月1日 00:00:00到现在的毫秒数 ) */
  20. @Test
  21. public void test2(){
  22. Instant ins = Instant.now(); //默认使用UTC时区
  23. System.out.println(ins+",,,"+ins.getEpochSecond());
  24. OffsetDateTime odt = ins.atOffset(ZoneOffset.ofHours(8));//中国在东八区
  25. System.out.println(odt);
  26. Instant ins1 = Instant.ofEpochSecond(5);
  27. System.out.println(ins1); //1970-01-01T00:00:05Z 从Unix元年偏移5s
  28. }
  29. /** * Duration : 用于计算两个“时间”间隔 * Period : 用于计算两个“日期”间隔 * */
  30. @Test
  31. public void test3() throws InterruptedException {
  32. Instant ins1 = Instant.now();
  33. Thread.sleep(1000);
  34. Instant ins2 = Instant.now();
  35. System.out.println("两个时间的间隔为--》"+Duration.between(ins1,ins2)); //两个时间的间隔为--》PT1S
  36. LocalDate date1 = LocalDate.of(2011,3,5);
  37. LocalDate date2 = LocalDate.now();
  38. Period pe = Period.between(date1,date2);
  39. System.out.println("两个日期的间隔为--》"+ pe+",,间隔的年为--》"+pe.getYears()); //两个日期的间隔为--》P6Y18D,,间隔的年为--》6
  40. }
  41. /* 时间校正器 TemporalAdjuster */
  42. @Test
  43. public void test4(){
  44. LocalDateTime ldt = LocalDateTime.now();
  45. System.out.println("今天几号--> "+ldt.getDayOfMonth()); //今天几号--> 23
  46. System.out.println("下个星期天是几号--》"+ ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY))); //下个星期天是几号--》2017-03-26T18:36:30.477
  47. // 自定义下一个工作日
  48. LocalDateTime dateTime = ldt.with((temporal)->{
  49. LocalDateTime lt = (LocalDateTime)temporal;
  50. DayOfWeek dow = lt.getDayOfWeek();
  51. if(DayOfWeek.FRIDAY.equals(dow)){
  52. return lt.plusDays(3);
  53. }else if(DayOfWeek.SATURDAY.equals(dow)){
  54. return lt.plusDays(2);
  55. }else{
  56. return lt.plusDays(1);
  57. }
  58. });
  59. System.out.println("下个工作日是--》"+dateTime); //下个工作日是--》2017-03-24T22:42:31.789
  60. }
  61. /* 格式化日期 */
  62. @Test
  63. public void test5(){
  64. // 自定义格式,当然也可以使用默认指定的格式
  65. DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  66. LocalDateTime ldt = LocalDateTime.now();
  67. System.out.println(format.format(ldt)); //2017-03-23 22:49:37
  68. //字符串转日期
  69. LocalDateTime ldt2 = LocalDateTime.parse("2017-11-12 23:10:05",format);
  70. System.out.println(ldt2); //2017-11-12T23:10:05
  71. }
  72. /* 带时区的日期 ZonedDate、ZonedTime、ZonedDateTime */
  73. @Test
  74. public void test6(){
  75. LocalDateTime ldt1 = LocalDateTime.now(ZoneId.of("Asia/Shanghai")); //Asia/shanghai time ->2017-03-23T22:57:21.084
  76. System.out.println("Asia/shanghai time ->"+ldt1);
  77. ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("America/Marigot"));
  78. System.out.println(zdt); //2017-03-23T10:59:43.708-04:00[America/Marigot]
  79. System.out.println(zdt.toLocalDateTime());//2017-03-23T11:00:49.177 转换为当前时区时间
  80. System.out.println("------------------------------------------------");
  81. //获取时区ID列表
  82. //ZoneId.getAvailableZoneIds().stream().forEach(System.out::println);
  83. }
  84. }

Optional

最大化减少空指针异常,Java 8引入了一个新的Optional类
Optional类是一个容器类,它可以保存类型T的值,代表这个值存在,或者保存为null,代表这个值不存在,
这是一个可以为null的容器对象,如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象

创造Optional类对象的API

  • Optional.of(T t):
  • 为非null的值创建一个Optional实例,t不能为空

    //调用工厂方法创建Optional实例
    Optional name = Optional.of(“tom”);
    //传入参数为null,抛出NullPointerException.
    Optional someNull = Optional.of(null);

Optional.ofNullable(T t):较常用

  • 创建一个Optional实例,t可为空

    //下面创建了一个不包含任何值的Optional实例
    Optional empty = Optional.ofNullable(null);

Optional.empty():

  • 创建一个空的Optional实例

判断Optional容器是否包含对象

  • boolean isPresent():
  • 非常容易理解,如果值存在返回true,否则返回false

void ifPresent(Consumer<? super T> ):

  • 如果有值就执行Consumer接口的实现代码,并且该值会作为参数传给它

    //ifPresent方法接受lambda表达式作为参数。
    //lambda表达式对Optional的值调用consumer进行处理。
    name.ifPresent((value) -> {

    1. System.out.println("The length of the value is: " + value.length());

    });

T orElse(T other):较常用

  • 如果有值则将其返回,否则返回指定的其它值

T orElseGet(Suppliper<? entend X> other):

  • 如果有值则将其返回,否则返回由Supplier接口实现提供的对象

    //orElseGet与orElse方法类似,区别在于orElse传入的是默认值,
    //orElseGet可以接受一个lambda表达式生成默认值。
    System.out.println(empty.orElseGet(() -> “Default Value”));
    System.out.println(name.orElseGet(() -> “Default Value”));

T orElseThrow(Suppliper<? entend X> exceptionSuppliper):

  • 如果有值则将其返回,否则抛出由Supplier接口实现提供的异常

    try {

    1. //orElseThrow与orElse方法类似。与返回默认值不同,
    2. //orElseThrow会抛出lambda表达式或方法生成的异常
    3. empty.orElseThrow(ValueAbsentException::new);

    } catch (Throwable ex) {

    1. //输出: No value present in the Optional instance
    2. System.out.println(ex.getMessage());

    }

总结

篇幅有限!篇幅有限!关于Java8新特性,就聊到这儿啦…啦…啦…

发表评论

表情:
评论列表 (有 0 条评论,353人围观)

还没有评论,来说两句吧...

相关阅读