一、 Lambda表达式

传统写法和使用lambda表达式的对比:

  1. public class TestDemo {
  2. @Test
  3. public void test(){
  4. //比较
  5. Comparator<Integer> comparable=new Comparator<Integer>() {
  6. @Override
  7. public int compare(Integer o1, Integer o2) {
  8. return o1.compareTo(o2);
  9. }
  10. };
  11. //lambda表达式比较
  12. Comparator<Integer> comparator=(x,y)-> Integer.compare(1,5);
  13. System.out.println(comparator);
  14. }
  15. //数据集合
  16. List<User> userList= Arrays.asList(
  17. new User("张三",18,5000),
  18. new User("李四",20,4000),
  19. new User("王五",46,2000),
  20. new User("小名",44,7000)
  21. );
  22. //传统方式
  23. @Test
  24. public void test02(){
  25. //传统方式 遍历集合 通过判断将符合条件的数据过滤出来
  26. //假设过滤条件改变 需要动原有代码
  27. List<User> users=new ArrayList<>();
  28. for (User user : userList) {
  29. if (user.getAge()>18){
  30. users.add(user);
  31. }
  32. }
  33. for (User user : users) {
  34. System.out.println(users);
  35. }
  36. }
  37. @Test
  38. //优化方式1 策略模式
  39. public void UserTest1(){
  40. //传入过滤参数
  41. List<User> userList = getMyUserFilter(this.userList, new UserByAge());
  42. for (User user : userList) {
  43. System.out.println(user);
  44. }
  45. }
  46. // 策略模式
  47. public List<User> getMyUserFilter(List<User> list,MyUserFilter<User> mp){
  48. List<User> ageList=new ArrayList<>();
  49. for (User user : list) {
  50. if (mp.test(user)){
  51. ageList.add(user);
  52. }
  53. }
  54. return ageList;
  55. }
  56. //方式二 匿名内部类
  57. @Test
  58. public void test2(){
  59. List<User> List=getMyUserFilter(userList, new MyUserFilter<User>() {
  60. @Override
  61. public boolean test(User t) {
  62. return t.getName().equals("张三");
  63. }
  64. });
  65. List.forEach(System.out::println);
  66. }
  67. //方式三 lambda表达式
  68. @Test
  69. public void test3(){
  70. List<User> myUserFilter = getMyUserFilter(userList, x -> x.getAge() > 18);
  71. myUserFilter.forEach(System.out::println);
  72. }
  73. //方式四 stream API
  74. @Test
  75. public void test4(){
  76. userList.stream().filter(x -> x.getAge() > 18).forEach(System.out::println);
  77. System.out.println("------------------------");
  78. userList.stream().map(User::getName).forEach(System.out::println);
  79. }
  80. }

MyUserFilter接口

  1. public interface MyUserFilter<User> {
  2. boolean test(User t);
  3. }

实现接口

  1. public class UserByAge implements MyUserFilter<User>{
  2. @Override
  3. public boolean test(User t) {
  4. //过滤年龄18的user
  5. return t.getAge()>18;
  6. }
  7. }
  • 可以看出来传统方式的处理,写的代码会比较繁琐和冗余。代码行数也比较多。
  • lambda表达式更加灵活,大大的减少了代码编写行数。
  • java8新特性学习 - 图1

二、Lmabda表达式的基础语法

  • Lambda 表达式在Java 语言中引入了一个新的语法元素和操作符。这个操作符为 “->” , 该操作符被称为 Lambda 操作符或剪头操作符。它将

Lambda 分为两个部分:
左侧:指定了 Lambda 表达式需要的所有参数
右侧:指定了 Lambda 体,即 Lambda 表达式要执行的功能。

  • 语法格式一:无参数,无返回值。

    1. public void test1(){
    2. Runnable runnable=new Runnable() {
    3. @Override
    4. public void run() {
    5. System.out.println("123");
    6. }
    7. };
    8. runnable.run();
    9. System.out.println("----------------------------------------");
    10. //Lambda表达式
    11. Runnable runnable1=()-> System.out.println("123");
    12. runnable1.run();
    13. }
  • 语法格式二:有参数,无返回值。

  • 如果只有一个参数,可以省略小括号

    1. @Test
    2. public void test2(){
    3. Consumer<String> consumer=(x)-> System.out.println(x);
    4. consumer.accept("123");
    5. ---------------------------------
    6. Consumer<String> consumer= x-> System.out.println(x);
    7. consumer.accept("123");
    8. }
  • 语法格式四:有两个以上参数,有返回值,并且lambda体中有多条语句。

  • 注意:如果只有一条语句,大括号和return可以不写 ```java @Test public void test3(){ Comparator comparator=(x,y)->{

    1. System.out.println("函数式接口");
    2. return Integer.compare(x,y);

    }; System.out.println(comparator.compare(5,8));


    Comparator integerComparator=(x,y)->Integer.compare(x,y); System.out.println(integerComparator.compare(10,5)); }

  1. 语法格式六:数据类型可以省略,因为可由编译器推断得出,称为“类型推断
  2. ```java
  3. Consumer<String> consumer=(String x)-> System.out.println(x);
  4. consumer.accept("123");
  5. Consumer<String> consumer=(x)-> System.out.println(x);
  6. consumer.accept("123");
  7. 在接口前面中定义了数据类型,所以后面的参数可以省略掉数据类型。

总结:
左边和右边都只有一个参数,一条语句。 ()和{ }可以省掉
左边定义了类型,右边参数可以省类型。

三、java8四大内置函数式接口

  • Consumer:消费型接口<br />

image.png

  • Supplier :供给型接口

image.png

  • Function:函数型接口

image.png

  • Predicate:断言型接口

image.png
image.png

四、方法引用的与构造器引用

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

对象 :: 实例方法

  1. User user=new User("试试",24,6000);
  2. Supplier<String> sup=()->user.getName();
  3. System.out.println(sup.get());
  4. System.out.println("---------------------------");
  5. Supplier<String> sup2=user::getName;
  6. System.out.println(sup2.get());

类 :: 静态方法

  1. Comparator<Integer> comparable=( x, y)->Integer.compare(x, y);
  2. Comparator<Integer> comparator=Integer::compare;


类 :: 实例方法**

  1. BiPredicate<String,String> biPredicate=(x,y)->x.equals(y);
  2. BiPredicate<String,String> bp=String::equals;
  3. boolean test = bp.test("12", "123");
  4. System.out.println(test);


构造器引用**

  1. //无参构造
  2. Supplier<User> supplier=User::new;
  3. User user = supplier.get();
  4. System.out.println(user);
  5. //有参构造
  6. Function<String,User> userFunction=(x)->new User(x);
  7. User user1 = userFunction.apply("吱吱吱");
  8. System.out.println(user1);
  9. //有参构造2
  10. Function<String,User> userFunction1=User::new;
  11. User user2 = userFunction1.apply("啊啊啊");
  12. System.out.println(user2);
  • 注意:
    ①方法引用所引用的方法的参数列表与返回值类型,需要与函数式接口中抽象方法的参数列表和返回值类型保持一致!
    ②若Lambda 的参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,格式: ClassName::MethodName

五、Stream API

流(Stream) 到底是什么呢?
是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
“集合讲的是数据,流讲的是计算!”

流(Stream) 到底是什么呢?
是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
“集合讲的是数据,流讲的是计算!”


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

image.png

Stream创建方式

  1. //1.可以通过Collection系列集合提供的stream()或者parallerStream()
  2. List<String> list=new ArrayList<>();
  3. Stream<String> stream = list.stream();
  4. //2.通过Arrays中的静态方法stream()获取
  5. User user[]=new User[10];
  6. Stream<User> stream1 = Arrays.stream(user);
  7. //3.通过Stream的静态of方法获取(底层还是Arrays的方法)
  8. Stream<String> stringStream = Stream.of("123", "675", "dasdsa", "gdf");
  9. //4.无限流方式 迭代
  10. Stream<Integer> iterate = Stream.iterate(0, x -> x + 2);
  11. iterate.limit(10).forEach(System.out::println);

中间操作

筛选与切片

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

    1. //多个中间操作可以连接起来形成一个流水线,除非流水
    2. 线上触发终止操作,否则中间操作不会执行任何的处理!
    3. 而在终止操作时一次性全部处理,称为“惰性求值”。
    4. @Test
    5. public void test3(){
    6. //中间操作;不会执行任何操作
    7. userList.stream().filter((x) ->
    8. {
    9. System.out.println("Stream API 的中间操作");
    10. return x.getSalary()>4000;
    11. }).limit(2).forEach(System.out::println);
    12. //终止操作:一次性执行全部内容,即‘堕性求值’
    13. // userStream.forEach(System.out::println);
    14. }

    映射

    image.png

    1. public void mapTest(){
    2. userList.stream().map(user -> {
    3. System.out.println("给员工每人涨1000元!");
    4. return user.getSalary()+1000;
    5. }).forEach(System.out::println);
    6. System.out.println("---------------------------------");
    7. //map 接收一个函数作为参数,该函数会被应用到每个元
    8. //素上,并将其映射成一个新的元素。
    9. List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd");
    10. Stream<Stream<Character>> streamStream = list.stream().map(TestStreamAPI::characterStream);
    11. streamStream.forEach(sm-> sm.forEach(
    12. System.out::println
    13. ));
    14. System.out.println("---------------------------------");
    15. //flatmap 接收一个函数作为参数,将流中的每个值都换成另
    16. //一个流,然后把所有流连接成一个流
    17. Stream<Character> characterStream = list.stream().flatMap(TestStreamAPI::characterStream);
    18. characterStream.forEach(System.out::println);
    19. }

    排序

    image.png

    1. @Test
    2. public void user(){
    3. List<String> list = Arrays.asList("eee", "bbb", "ccc", "ddd","aaa");
    4. //自然排序
    5. list.stream().sorted().forEach(System.out::println);
    6. System.out.println("--------------------------------------------");
    7. //自定义排序
    8. userList.stream().sorted((x1,x2)->{
    9. //按年龄排序
    10. return x1.getAge().equals(x2.getAge()) ? x1.getName().compareTo(x2.getName()):x1.getAge().compareTo(x2.getAge());
    11. }).forEach(System.out::println);
    12. }

    终止操作

    终端操作会从流的流水线生成结果。其结果可以是任何不是流的
    值,例如:List、Integer,甚至是 void 。
    image.png image.png```java List userList= Arrays.asList(

    1. new User("张三",18,5000, Status.FREE),
    2. new User("李四",20,4000, Status.BUSY),
    3. new User("王五",46,2000, Status.VOCATION),
    4. new User("小名",44,7000, Status.FREE),
    5. new User("小红",16,2000, Status.BUSY),
    6. new User("李雷",33,10000, Status.FREE)

    ); //allMatch(Predicate p) 检查是否匹配所有元素 //anyMatch(Predicate p) 检查是否至少匹配一个元素 //noneMatch(Predicate p) 检查是否没有匹配所有元素 //findFirst() 返回第一个元素 //findAny() 返回当前流中的任意元素 // count() 返回流中元素总数 //max(Comparator c) 返回流中最大值 //min(Comparator c) 返回流中最小值 //forEach(Consumer c) 内部迭代(使用 Collection 接口需要用户去做迭 //代,称为外部迭代。相反,Stream API 使用内部迭代——它帮你把迭代做了)

    @Test public void test(){ //allMatch(Predicate p) 检查是否匹配所有元素 boolean b = userList.stream().anyMatch(user -> user.getStatus().equals(Status.BUSY)); System.out.println(b); //anyMatch(Predicate p) 检查是否至少匹配一个元素 //noneMatch(Predicate p) 检查是否没有匹配所有元素

    //findFirst() 返回第一个元素 Optional first = userList.stream().sorted((u1, u2) -> Integer.compare(u1.getSalary(), u2.getSalary()))

    1. .findFirst();

    System.out.println(first.get());

    //findAny() 返回当前流中的任意元素 Optional first1 = userList.stream().filter(x -> x.getStatus().equals(Status.BUSY)).findFirst(); System.out.println(first1.get());

    // count() 返回流中元素总数 //max(Comparator c) 返回流中最大值 Optional max = userList.stream().max((u1, u2) -> Integer.compare(u1.getSalary(), u2.getSalary())); System.out.println(max.get()); } ```

归约

image.png

  1. //reduce(T iden, BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。 返回
  2. @Test
  3. public void test01(){
  4. //获取所有员工的工资的和
  5. Optional<Integer> reduce = userList.stream().map(User::getSalary).reduce(Integer::sum);
  6. System.out.println(reduce.get());
  7. } //reduce(T iden, BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。 返回
  8. @Test
  9. public void test01(){
  10. //获取所有员工的工资的和
  11. Optional<Integer> reduce = userList.stream().map(User::getSalary).reduce(Integer::sum);
  12. System.out.println(reduce.get());
  13. }


image.png
Collector 接口中方法的实现决定了如何对流执行收集操作(如收集到 List、Set、Map)。但是 Collectors 实用类提供了很多静态
方法,可以方便地创建常见收集器实例,具体方法与实例如下表
image.png
image.png
image.pngimage.png

  1. // collect(Collector c) 将流转换为其他形式。接收一个 Collector接口的
  2. // 实现,用于给Stream中元素做汇总的方法
  3. @Test
  4. public void test02(){
  5. List<User> collect = userList.stream().filter((user) -> user.getSalary() > 2000).
  6. collect(Collectors.toList());
  7. collect.forEach(System.out::println);
  8. System.out.println("------------------------------------");
  9. //工资总数
  10. Long collect1 = userList.stream().collect(Collectors.counting());
  11. System.out.println(collect1);
  12. System.out.println("------------------------------------");
  13. //工资平均值
  14. Double collect2 = userList.stream().collect(Collectors.averagingDouble(User::getSalary));
  15. System.out.println(collect2);
  16. System.out.println("------------------------------------");
  17. //工资总和
  18. Double collect3 = userList.stream().collect(Collectors.summingDouble(User::getSalary));
  19. System.out.println(collect3);
  20. System.out.println("------------------------------------");
  21. //工资最大值
  22. Optional<User> collect4 = userList.stream()
  23. .collect(Collectors.maxBy((x1, x2) -> Double.compare(x1.getSalary(), x2.getSalary())));
  24. System.out.println(collect4.get());
  25. System.out.println("------------------------------------");
  26. //工资最小值
  27. Optional<Integer> collect5 = userList.stream().map(User::getSalary)
  28. .collect(Collectors.minBy((x1, x2) -> (int) Double.compare(x1, x2)));
  29. System.out.println(collect5.get());
  30. System.out.println("------------------------------------");
  31. //分组
  32. Map<Status, List<User>> collect6 = userList.stream().collect(Collectors.groupingBy(User::getStatus));
  33. collect6.forEach((k,v)-> System.out.println(k+" "+v));
  34. System.out.println("------------------------------------");
  35. //多级分组
  36. Map<Status, Map<String, List<User>>> collect7 = userList.stream()
  37. .collect(Collectors.groupingBy(User::getStatus, Collectors.groupingBy((x) -> {
  38. if (x.getAge() > 20) {
  39. return "青年";
  40. } else if (x.getAge() > 60) {
  41. return "老年";
  42. } else {
  43. return "青少年";
  44. }
  45. })));
  46. collect7.forEach((k,v)->v.forEach((k2,v2)-> System.out.println(k+" "+k2+" "+v2)
  47. ));
  48. }

并行流和串行流

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

  1. public class ForkJoinCalculate extends RecursiveTask<Long> {
  2. private Long start;
  3. private Long end;
  4. //临界值
  5. private static final long THRESOLD=10000;
  6. public ForkJoinCalculate(Long start, Long end) {
  7. this.start = start;
  8. this.end = end;
  9. }
  10. @Override
  11. protected Long compute() {
  12. //结束-开始
  13. Long length=end-start;
  14. //小于临界值用for
  15. if (length<=THRESOLD){
  16. long sum=0;
  17. for (long i = start; i <end ; i++) {
  18. sum+=i;
  19. }
  20. return sum;
  21. }else {
  22. //大于临界值 用ForkJoin
  23. long middle=(start+end)/2;
  24. //左边 例: 0-5
  25. ForkJoinCalculate left=new ForkJoinCalculate(start,middle);
  26. left.fork();
  27. //右边 例: 6-10
  28. ForkJoinCalculate right=new ForkJoinCalculate(middle+1,end);
  29. right.fork();
  30. //连接总和
  31. return left.join()+right.join();
  32. }
  33. }
  34. }
  35. //测试代码
  36. //Fork Join框架
  37. @Test
  38. public void test(){
  39. Instant start = Instant.now();
  40. ForkJoinPool joinPool=new ForkJoinPool();
  41. ForkJoinTask<Long> task=new ForkJoinCalculate(0L,100000000L);
  42. Long sum = joinPool.invoke(task);
  43. Instant end = Instant.now();
  44. System.out.println("耗费时间:"+ Duration.between(start,end).toMillis());
  45. System.out.println(sum);
  46. }
  47. //stream并行流
  48. @Test
  49. public void test02(){
  50. long reduce = LongStream.rangeClosed(0, 1000000000L).parallel().reduce(
  51. 0, Long::sum
  52. );
  53. }
  • java8 StreamAPI并行流底层使用的是ForkJoin框架
  • 处理大数据时比较有明显区别

Optional类

image.png

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

image.png
image.png

传统时间格式化的线程安全问题

  1. package day02.com.atduigu.java8;
  2. importjava.text.SimpleDateFormat;
  3. import java.time.LocalDate;
  4. import java.time.format.DateTimeFormatter;
  5. import java.util.ArrayList;
  6. import java.util.Date;
  7. import java.util.List;
  8. import java.util.concurrent.*;
  9. public class TestSimpleDateFormat {
  10. publicstatic void main(String[] args) throws ExecutionException, Exception {
  11. /*Callable<Date> task = new Callable<Date>() {
  12. @Override
  13. public Date call() throws Exception {
  14. return DateFormatThreadLocal.convert("20161218");
  15. }
  16. };
  17. ExecutorService pool = Executors.newFixedThreadPool(10);
  18. List<Future<Date>> results = new ArrayList<>();
  19. for(int i = 0; i < 10; i++) {
  20. results.add(pool.submit(task));
  21. }
  22. for(Future<Date> future : results){
  23. System.out.println(future.get());
  24. }
  25. pool.shutdown();*/
  26. DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
  27. Callable<LocalDate> task = new Callable<LocalDate>() {
  28. @Override
  29. public LocalDate call() throws Exception {
  30. return LocalDate.parse("20161218", dtf);
  31. }
  32. };
  33. ExecutorService pool = Executors.newFixedThreadPool(10);
  34. List<Future<LocalDate>> results = new ArrayList<>();
  35. for(int i = 0; i < 10; i++) {
  36. results.add(pool.submit(task));
  37. }
  38. for(Future<LocalDate> future : results){
  39. System.out.println(future.get());
  40. }
  41. pool.shutdown();
  42. }
  43. }
  44. packageday02.com.atduigu.java8;
  45. importjava.text.DateFormat;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;
  46. public class DateFormatThreadLocal {
  47. private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>(){
  48. @Override protectedDateFormat initialValue() {
  49. return new SimpleDateFormat("yyyyMMdd");
  50. }
  51. };
  52. public static Date convert(String source) throws ParseException {
  53. returndf.get().parse(source);
  54. }
  55. }

API-本地时间与时间戳

  1. package day02.com.atduigu.java8;
  2. import org.junit.Test;
  3. import java.time.*;
  4. public class TestLocalDateTime {
  5. //3.
  6. //Duration:计算两个“时间”之间的间隔
  7. //Period:计算两个“日期之间的间隔”
  8. @Test
  9. public void tets4(){
  10. LocalDate ld1 = LocalDate.of(2015, 1,1);
  11. LocalDate ld2 = LocalDate.now();
  12. Period period = Period.between(ld1, ld2);
  13. System.out.println(period);
  14. System.out.println(period.getYears());
  15. System.out.println(period.getMonths());
  16. System.out.println(period.getDays());
  17. }
  18. @Test
  19. public void tets3(){
  20. Instant ins1 = Instant.now();
  21. try {
  22. Thread.sleep(1000);
  23. } catch (InterruptedException e) {
  24. e.printStackTrace();
  25. }
  26. Instant ins2 = Instant.now();
  27. Duration duration = Duration.between(ins1, ins2);
  28. System.out.println(duration.toMillis());
  29. System.out.println("-------------------------");
  30. LocalTime lt1 = LocalTime.now();
  31. try {
  32. Thread.sleep(1000);
  33. } catch (InterruptedException e) {
  34. e.printStackTrace();
  35. }
  36. LocalTime lt2 = LocalTime.now();
  37. System.out.println(Duration.between(lt1,lt2).toMillis());
  38. }
  39. //2. Instant : 时间戳(以Unix 元年:1970年1月1日 00:00:00 到某个时间之间的毫秒值)
  40. @Test
  41. public void test2(){
  42. Instant ins1 = Instant.now();// 默认获取 UTC 时区
  43. System.out.println(ins1);
  44. OffsetDateTime odt = ins1.atOffset(ZoneOffset.ofHours(8));
  45. System.out.println(odt);
  46. System.out.println(ins1.toEpochMilli());
  47. Instant ins2 = Instant.ofEpochSecond(60);
  48. System.out.println(ins2);
  49. }
  50. //1. LocalDate LocalTime LocalDateTime
  51. @Test
  52. public void test1(){
  53. LocalDateTime ldt = LocalDateTime.now();
  54. System.out.println(ldt);
  55. LocalDateTime ldt2 = LocalDateTime.of(2015, 10, 19, 13, 22, 33);
  56. System.out.println(ldt2);
  57. LocalDateTime ldt3 = ldt.plusYears(2);
  58. System.out.println(ldt3);
  59. LocalDateTime ldt4 = ldt.minusMonths(2);
  60. System.out.println(ldt4);
  61. System.out.println(ldt.getYear());
  62. System.out.println(ldt.getMonthValue());
  63. System.out.println(ldt.getDayOfMonth());
  64. System.out.println(ldt.getHour());
  65. System.out.println(ldt.getMinute());
  66. System.out.println(ldt.getSecond());
  67. }
  68. }

API-时间校正器

java8新特性学习 - 图23

  1. package day02.com.atduigu.java8;
  2. importorg.junit.Test;
  3. importjava.time.*;import java.time.temporal.Temporal;importjava.time.temporal.TemporalAdjuster;import java.time.temporal.TemporalAdjusters;
  4. public classTestLocalDateTime {
  5. //时间校正器
  6. @Test
  7. public void tett5(){
  8. LocalDateTime ldt = LocalDateTime.now();
  9. System.out.println(ldt);
  10. LocalDateTime ldt2 = ldt.withDayOfMonth(10);
  11. System.out.println(ldt2);
  12. LocalDateTime ldt3 = ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
  13. System.out.println(ldt3);
  14. //自定义:下一个工作日
  15. LocalDateTime ldt5 = ldt.with((l) -> {
  16. LocalDateTime ldt4 = (LocalDateTime) l;
  17. DayOfWeek daw = ldt4.getDayOfWeek();
  18. if(daw.equals(DayOfWeek.FRIDAY)) {
  19. return ldt4.plusDays(3);
  20. } else if (daw.equals(DayOfWeek.SATURDAY)) {
  21. return ldt4.plusDays(2);
  22. } else {
  23. return ldt4.plusDays(1);
  24. }
  25. });
  26. System.out.println(ldt5);
  27. }
  28. //3.
  29. //Duration:计算两个“时间”之间的间隔
  30. //Period:计算两个“日期之间的间隔”
  31. @Test public void tets4(){
  32. LocalDate ld1= LocalDate.of(2015, 1,1);
  33. LocalDate ld2= LocalDate.now();
  34. Period period = Period.between(ld1, ld2);
  35. System.out.println(period);
  36. System.out.println(period.getYears());
  37. System.out.println(period.getMonths());
  38. System.out.println(period.getDays());
  39. }
  40. @Test public void tets3(){
  41. Instant ins1= Instant.now();
  42. try{
  43. Thread.sleep(1000);
  44. } catch(InterruptedException e) {
  45. e.printStackTrace();
  46. }
  47. Instant ins2 = Instant.now();
  48. Duration duration = Duration.between(ins1, ins2);
  49. System.out.println(duration.toMillis());
  50. System.out.println("-------------------------");
  51. LocalTime lt1 = LocalTime.now();
  52. try{
  53. Thread.sleep(1000);
  54. } catch(InterruptedException e) {
  55. e.printStackTrace();
  56. }
  57. LocalTime lt2 = LocalTime.now();
  58. System.out.println(Duration.between(lt1,lt2).toMillis());
  59. }
  60. //2. Instant : 时间戳(以Unix 元年:1970年1月1日 00:00:00 到某个时间之间的毫秒值)
  61. @Test public void test2(){
  62. Instant ins1= Instant.now();// 默认获取 UTC 时区
  63. System.out.println(ins1);
  64. OffsetDateTime odt = ins1.atOffset(ZoneOffset.ofHours(8));
  65. System.out.println(odt);
  66. System.out.println(ins1.toEpochMilli());
  67. Instant ins2 = Instant.ofEpochSecond(60);
  68. System.out.println(ins2);
  69. }
  70. //1. LocalDate LocalTime LocalDateTime @Test public void test1(){
  71. LocalDateTime ldt = LocalDateTime.now();
  72. System.out.println(ldt);
  73. LocalDateTime ldt2 = LocalDateTime.of(2015, 10, 19, 13, 22, 33);
  74. System.out.println(ldt2);
  75. LocalDateTime ldt3 = ldt.plusYears(2);
  76. System.out.println(ldt3);
  77. LocalDateTime ldt4 = ldt.minusMonths(2);
  78. System.out.println(ldt4);
  79. System.out.println(ldt.getYear());
  80. System.out.println(ldt.getMonthValue());
  81. System.out.println(ldt.getDayOfMonth());
  82. System.out.println(ldt.getHour());
  83. System.out.println(ldt.getMinute());
  84. System.out.println(ldt.getSecond());
  85. }
  86. }

API-时间格式化与时区的处理

java8新特性学习 - 图24

重复注解与类型注解

java8新特性学习 - 图25

  1. package day02.com.atduigu.java8;
  2. import java.lang.annotation.Repeatable;
  3. import java.lang.annotation.Retention;
  4. import java.lang.annotation.RetentionPolicy;
  5. import java.lang.annotation.Target;
  6. import static java.lang.annotation.ElementType.*;
  7. import static java.lang.annotation.ElementType.CONSTRUCTOR;
  8. import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
  9. @Repeatable(MyAnnotations.class)
  10. @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, TYPE_PARAMETER})
  11. @Retention(RetentionPolicy.RUNTIME)
  12. public @interface MyAnnotation {
  13. String value() default "atguigu";
  14. }
  15. package day02.com.atduigu.java8;
  16. import java.lang.annotation.Repeatable;
  17. import java.lang.annotation.Retention;
  18. import java.lang.annotation.RetentionPolicy;
  19. import java.lang.annotation.Target;
  20. import static java.lang.annotation.ElementType.*;
  21. import static java.lang.annotation.ElementType.CONSTRUCTOR;
  22. import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
  23. @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
  24. @Retention(RetentionPolicy.RUNTIME)
  25. public @interface MyAnnotations {
  26. MyAnnotation[] value();
  27. }
  28. package day02.com.atduigu.java8;
  29. import com.sun.istack.internal.NotNull;
  30. import org.junit.Test;
  31. import java.lang.reflect.Method;
  32. /*
  33. 重复注解与类型注解
  34. */
  35. public class TestAnnotation {
  36. //checker framework
  37. private @NotNull Object obj = null;
  38. @Test
  39. public void test1() throws Exception {
  40. Class<TestAnnotation> clazz = TestAnnotation.class;
  41. Method m1 = clazz.getMethod("show");
  42. MyAnnotation[] mas = m1.getAnnotationsByType(MyAnnotation.class);
  43. for (MyAnnotation myAnnotation: mas) {
  44. System.out.println(myAnnotation.value());
  45. }
  46. }
  47. @MyAnnotation("Hello")
  48. @MyAnnotation("World")
  49. public void show(@MyAnnotation("abc") String str){
  50. }
  51. }