文章目录

  • Java8新特性
    • 速度快
    • 代码更少(增加了新的语法,lamda表达式)(主要)
    • 强大的Stream API(主要)
    • 便于并行
    • 最大减少空指针异常(Optional API)
    • 提供了线程安全的时间类
  • Lomda表达式(非常重要)
    • 策略模式
      • 定义
      • 策略模式应用的背景
    • 具体语法
  • Stream流(非常重要!!)
    • 下文使用的学生对象以及数据是上文所提到的
    • Stream API 的必须做的操作流程
    • 创建Stream流对象与中间步骤
    • 终止步骤
  • Optional API
  • 提供了线程安全的时间类
    • 关于JDK7时间类线程不安全的测试与解决方法
    • 常用方法

Java8新特性

速度快

  1. 优化了HashMap与HashSet集合类的数据结构

    • JDK1.7版本采用的是哈希表(数组)+链表而JDK1.8采用的是哈希表+链表+红黑树

    • 哈希表+数组+红黑树的概述

    • 基本原理:先得到对象的hashcode值,对数组长度取余得到数组下标,若是该数组下标的位置上无元素,直接放入,若是有使用equals方法进行比较,若是相同则覆盖,若是不同则将该对象放入链表的头部其余元素后移(1.8放入链尾)

    • 如何避免Hash冲突(碰撞)

      • 将重写toHashCode与equals方法保持一致:equals为true时HashCode值相同,对象相同时equals值为true
      • 加载因子(0.75): 当使用的哈希表的容量达到了限定容量的百分之75就对哈希表进行扩容,扩容成原来的两倍
    • 如何优化

      • 当链表的长度大于8并且HashMap的总容量大于64时就将链表转为红黑树
    • 红黑树除了在增加元素的效率比不上链表,查改删的效率都高于链表。而且使用了红黑树,在扩容以后,就不用再去重新计算hashcode的值进行重组,只需要将原来红黑树的某一部分取出来,将原来红黑树所在的哈希表下标加上原来哈希表的容量的新下标,放入新的哈希表的新下标即可。

  2. 优化了ConCurrentHashMap与ConcurrentHashSet

    • 取消了concurrentLevel而使用CAS算法
  3. 优化了JVM虚拟机的内存结构了

    • 将方法区彻底的从堆内存中的永久区(PremGen)分离开,以前堆内存的永久区就是方法区,分离出来的方法区使用的是物理内存,并且物理内存有多,方法区就能用多大,极大的减少了方法区被垃圾回收机制回收的可能性,新分离出来的方法区叫做(MetaSpace(元空间))

代码更少(增加了新的语法,lamda表达式)(主要)

强大的Stream API(主要)

  • 使用StreamAPI操作集合的数据,将会得到极大的效率提升

便于并行

最大减少空指针异常(Optional API)

提供了线程安全的时间类

Lomda表达式(非常重要)

策略模式

定义

  • 策略模式是行为模式之一,它对一系列的算法加以封装,为所有算法定义一个抽象的算法接口,并通过继承该抽象算法接口对所有的算法加以封装和实现,具体的算法选择交由客户端决定(策略)。Strategy模式主要用来平滑地处理算法的切换。

策略模式应用的背景

  • 需求:将学生按照不同的条件查询出来

    • 学生类如下:
     @Datepublic class Student implements Comparable{private String name;private Integer age;private double consumption;private Status status;public enum Status{study,rest,sleep;}
    
    • 学生数据如下:
    public class StudentDao {public List<Student> selectAll() {ArrayList<Student> students = new ArrayList<>();students.add(new Student("张三", 18, 1000, Student.Status.study));students.add(new Student("王五", 21, 2000, Student.Status.rest));students.add(new Student("赵六", 29, 3000, Student.Status.sleep));students.add(new Student("阿七", 34, 4000, Student.Status.study));students.add(new Student("六四", 40, 5000, Student.Status.rest));return students;}}
    
  • 在Java8中的解决方案:

    • 定义一个函数式接口
     @FunctionalInterfacepublic interface StudentDaoFilter<T> {public boolean filter(T t);}
    
    • 实现函数式接口完成策略的实现
    //有了Java8的函数式接口后,就可以不用先实现个匿名内部类后,只需要关注于具体的策略实现
    public class MainSoluton {public static void main(String[] args) {StudentDao studentDao = new StudentDao();List<Student> students = studentDao.selectAll();//根据消费水平查List<Student> s1 = filterStudentDao(students, (student -> student.getConsumption() > 3000));System.out.println("----------");System.out.println(s1);//根据消费水平与学习状态查List<Student> s2 = filterStudentDao(students, (student -> student.getConsumption() > 3000 && student.getStatus().equals(Student.Status.study)));System.out.println("----------");s2.forEach(System.out::println);System.out.println("----------");//按照状态查List<Student> s3 = filterStudentDao(students, student -> student.getStatus().equals(Student.Status.rest));s3.forEach(System.out::println);}public static List<Student> filterStudentDao(List<Student> oldStudents, StudentDaoFilter<Student> studentDaoFilter) {ArrayList<Student> newStudents = new ArrayList<>();for (Student s : oldStudents) {if (studentDaoFilter.filter(s)) {newStudents.add(s);}}return newStudents;}}
    

具体语法

  • 基本语法:

    /*
    * 一、Lambda 表达式的基础语法:Java8中引入了一个新的操作符 "->" 该操作符称为箭头操作符或 Lambda 操作符
    *                           箭头操作符将 Lambda 表达式拆分成两部分:
    *
    * 左侧:Lambda 表达式的参数列表
    * 右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体
    *
    * 语法格式一:无参数,无返回值
    *       () -> System.out.println("Hello Lambda!");
    *
    * 语法格式二:有一个参数,并且无返回值
    *       (x) -> System.out.println(x)
    *
    * 语法格式三:若只有一个参数,小括号可以省略不写
    *       x -> System.out.println(x)
    *
    * 语法格式四:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句
    *       Comparator<Integer> com = (x, y) -> {
    *           System.out.println("函数式接口");
    *           return Integer.compare(x, y);
    *       };
    *
    * 语法格式五:若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写
    *       Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
    *
    * 语法格式六:Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断”
    *       (Integer x, Integer y) -> Integer.compare(x, y);
    *
    * 上联:左右遇一括号省
    * 下联:左侧推断类型省
    * 横批:能省则省
    **/
    public class MainTest1 {//()-> System.out.println("线程运行");@Testpublic void test1() {Runnable runnable = () -> System.out.println("线程运行");runnable.run();}//(x)->System.out.println("消费者已消费");@Testpublic void test2() {Consumer consumer = (x) -> System.out.println("消费者已消费" + x + "元");consumer.accept(500);}//(x,y)->x.comparetor(y);@Testpublic void test3(){Comparator<Integer> comparator=(x,y)-> x.compareTo(y);int compare = comparator.compare(3, 2);System.out.println(compare);}//需要写多条语句时@Testpublic void test4(){Comparator<Integer> comparator=(x,y)->{System.out.println(x+y);return x.compareTo(y);};System.out.println(comparator.compare(1,2));}
    }
    
  • Lamda表达式对于函数式接口的支持以及内置的四大核心函数式接口(*)

    /*** Lamda表达式对于“函数式接口”的支持* 函数式接口:接口中只有一个抽象方法的接口,称为函数式接口。 * 可以使用注解 @FunctionalInterface 修饰,该注解用于检查是否是函数式接口。* Java8 内置的四大核心函数式接口** Consumer<T> : 消费型接口*         void accept(T t);** Supplier<T> : 供给型接口*      T get();** Function<T, R> : 函数型接口*        R apply(T t);** Predicate<T> : 断言型接口*         boolean test(T t);**/public class MainTest2 {//Consumer<T>:消费型接口@Testpublic void test01(){Consumer consumer=(x)->System.out.println(x);consumer.accept("I am consumer!");}//Supplier<T>:生产者接口@Testpublic void test02(){Supplier supplier=()-> "I am Supplier";System.out.println(supplier.get());}//Function<T,R>:函数式型接口@Testpublic void test03(){Function<Integer,Integer> function=(x)->x;System.out.println(function.apply(1));}//Predicate<T>:断言接口@Testpublic void test4(){Predicate<Integer> predicate=(x)->x.equals(2);System.out.println(predicate.test(1));}
    }
    
  • Lamda表达式表现形式:方法,对象,构造器引用(可以理解为:对于lamda表达式的简写)

    /*
    * 一、方法引用:若 Lambda 体中的功能,已经有方法提供了实现,可以使用方法引用
    *             (可以将方法引用理解为 Lambda 表达式的另外一种表现形式)
    *
    * 1. 对象的引用 :: 实例方法名
    *
    * 2. 类名 :: 静态方法名
    *
    * 3. 类名 :: 实例方法名
    *
    * 注意:
    *    ①方法引用所引用的方法的参数列表与返回值类型,需要与函数式接口中抽象方法的参数列表和返回值类型保持一致!
    *    ②若Lambda 的参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,可以使用"类名::实例方法名"的语法格式: ClassName::MethodName
    *
    * 二、构造器引用 :构造器的参数列表,需要与函数式接口中参数列表保持一致!
    * 1. 类名 :: new
    * 三、数组引用
    *   类型[] :: new;
    *
    *
    */
    public class MainTest3 {//实例引用::实例方法名@Testpublic void test01(){//这句话相当于实现了一个Consumer的函数式接口Consumer consumer=System.out::println;//这里会打印"nihao"consumer.accept("nihao");Student student = new Student();//这里相当于实现了一个Supplier的函数式接口Supplier supplier=student::getAge;//这里打印学生的名字System.out.println(supplier.get());}//类名::静态方法名@Testpublic void test02(){//前两个泛型是形参,最后一个是返回值BiFunction<Double,Double,Double> biFunction= Math::max;//输出30.00System.out.println(biFunction.apply(1.12,30.00));}//类名::实例方法名@Testpublic void test03(){BiPredicate<String,String> biPredicate=String::equals;//这里输出trueSystem.out.println(biPredicate.test("nihao","nihao"));}//构造器引用@Testpublic void test04(){//前一个是形参后一个是返回值Function<String,Student> function=Student::new;//这里会输出一个学生对象System.out.println(function.apply("zhangsan"));BiFunction<String,Integer,Student> f2=Student::new;System.out.println(f2.apply("wangwu",25));}//数组引用@Testpublic void test05(){Function<Integer,Student[]> function=Student[]::new;//这里创建了一个长度为10的学生对象数组。System.out.println(function.apply(10).length);}}
    

Stream流(非常重要!!)

下文使用的学生对象以及数据是上文所提到的

Stream API 的必须做的操作流程

  1. 创建Stream流对象
  2. 中间步骤
  3. 终止步骤
  • 这里需要特别注意:

    • 惰性求值现象:只有当做终止操作时,所有的中间操作才会一次性执行

创建Stream流对象与中间步骤

 public class MainTest01 {private List<Student> students = new StudentDao().selectAll();//创建流@Testpublic void test1() {/*** 一:* Collection接口提供了两种抽象方法:stream():创建顺序流,parallelStream():创建并行流* 之间的区别,这里可以简单的理解为,并行流使用了fork/join框架,并行流会在数据量大的时候处理的效率会更高*/Stream<Student> studentStream = students.stream();//创建顺序流Stream<Student> parallelStream = students.parallelStream();//创建并行流//2:通过Arrays工具类的stream()流获得一个数组的顺序流Function<Integer, Integer[]> f1 = Integer[]::new;Stream<Integer> integerStream = Arrays.stream(f1.apply(10));//3:通过Stream类中的静态方法of()来获取流Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);//4:创建无限流//迭代Stream<Integer> integerStream1 = Stream.iterate(0, x -> x + 2).limit(10);//limit()流的终止操作,返回一个该截取长度的流integerStream1.forEach(System.out::println);//生成Stream<Double> tStream = Stream.generate(Math::random).limit(2);tStream.forEach(System.out::println);}//中间步骤@Testpublic void test2() {/*筛选与切片filter——接收 lambda , 从流中排除某些元素。limit——截断流,使其元素不超过给定数量。skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补distinct——筛选,通过流所生映射映射map——接收 Lambda , 将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。flatMap——接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一元素的 hashcode() 和 equals() 去除重复元素排序sorted()——自然排序sorted(Comparator com)——定制排序*///filter():按指定规则过滤students.stream().filter(student -> student.getAge()>38).forEach(System.out::println);//limit(n):截取前n个元素System.out.println("---------------------------");students.stream().filter(student -> student.getAge()>38).limit(2).forEach(System.out::println);//skip(n):跳过前n个元素System.out.println("---------------------------");students.stream().filter(student -> student.getAge()>38).skip(2).forEach(System.out::println);//distinct():去除重复元素根据hashcode()与equals()方法System.out.println("---------------------------");students.stream().distinct().forEach(System.out::println);//映射map():为所有元素进行相同的操作System.out.println("---------------------------");students.stream().map(student -> student.getName()).forEach(System.out::println);//flatMap():若map的映射是将其中元素转换成流,那么flatmap可以将映射后形成的一个个小流,合并成一个大流//需求将每一个字符串集合的每一个字符串分开成单个字符,并且依次打印每一个字符List<String> strings = Arrays.asList("aaa", "bbb", "ccc", "eee");Stream<Stream<Character>> listStream = strings.stream().map(MainTest01::toChar);listStream.forEach(clist->clist.forEach(System.out::println));System.out.println("---------------------------");Stream<Character> characterStream = strings.stream().flatMap(MainTest01::toChar);characterStream.forEach(System.out::println);//自然排序sorted():对象所属的实体类实现了Comparable接口重写了compareTo()方法System.out.println("------------------------------");students.stream().sorted().forEach(System.out::println);//定制排序sorted():自己定制规则进行排序System.out.println("------------------------------");students.stream().sorted((s1,s2)->{return -s1.compareTo(s2);}).forEach(System.out::println);}//将字符串转换为字符数组的方法public static Stream<Character> toChar(String s){ArrayList<Character> characters = new ArrayList<>();for (Character c : s.toCharArray()) {characters.add(c);}return characters.stream();}//惰性求值现象:只有当做终止操作时,所有的中间操作才会一次性执行@Testpublic void test3(){Stream<Student> studentStream = students.stream().filter(student -> {System.out.println("过滤开始");return student.getAge() > 28;});System.out.println("结束流操作开始");studentStream.forEach(System.out::println);}}

终止步骤

//3. 终止操作
public class MainTest02 {private List<Student> students=new StudentDao().selectAll();/*allMatch——检查是否匹配所有元素anyMatch——检查是否至少匹配一个元素noneMatch——检查是否没有匹配的元素findFirst——返回第一个元素findAny——返回当前流中的任意元素count——返回流中元素的总个数max——返回流中最大值min——返回流中最小值*/@Testpublic void test01(){//allMatch()boolean allMatch = students.stream().allMatch(student -> Student.Status.rest.equals(student.getStatus()));System.out.println(allMatch);//anyMatch()boolean anyMatch = students.stream().anyMatch(student -> student.getStatus().equals(Student.Status.study));System.out.println(anyMatch);//noneMatch()boolean noneMatch = students.stream().noneMatch(student -> student.getStatus().equals(Student.Status.study));System.out.println(noneMatch);//findFirst()返回第一个元素Optional<Student> first = students.stream().findFirst();System.out.println(first);//findAny()返回当前流中任意元素Optional<Student> any = students.stream().findAny();System.out.println(any);//max()返回流中最大值Optional<Double> max = students.stream().map(Student::getConsumption).max(Double::compareTo);System.out.println(max);//min()返回流中最小值Optional<Double> min = students.stream().map(Student::getConsumption).min(Double::compareTo);System.out.println(min);//count()返回流中元素的个数long count = students.stream().count();System.out.println(count);}/*归约reduce(T identity, BinaryOperator) / reduce(BinaryOperator) ——可以将流中元素反复结合起来,得到一个值。*/@Testpublic void test02(){//方式一:从指定的初始值开始归约Double sum = students.stream().map(Student::getConsumption).reduce(0.0, (x, y) -> x + y);System.out.println(sum);//方式二:不指定初始值的归约Optional<Double> sum2 = students.stream().map(Student::getConsumption).reduce(Double::sum);System.out.println(sum2);//map与reduce的结合往往可以用于大数据的处理上//需求:搜索学生中名字出现“六”的个数Optional<Integer> countLiu = students.stream().map(Student::getName).map(name -> {if (name.contains("六")) {return 1;} else {return 0;}}).reduce(Integer::sum);System.out.println(countLiu);}/*collect——将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法,将流转换为各种集合*/@Testpublic void test03(){//list集合List<String> nameList = students.stream().map(Student::getName).collect(Collectors.toList());System.out.println("list集合:"+nameList);//set集合Set<String> nameSet = students.stream().map(Student::getName).collect(Collectors.toSet());System.out.println("Set集合:"+nameSet);//转Set集合的第二种方式HashSet<String> nameHashSet = students.stream().map(Student::getName).collect(Collectors.toCollection(HashSet::new));System.out.println("HashSet集合:"+nameHashSet);//转Map集合:map的value为整个对象,注意当流中有重复元素的时候转map会抛出异常Map<String, Student> studentMap = students.stream().collect(Collectors.toMap(Student::getName, student -> student));studentMap.forEach((key,value)->{System.out.println("key="+key+":"+"map"+value);});//转Map集合:map的value为对象的单一属性Map<String, Double> studentMap1 = students.stream().collect(Collectors.toMap(Student::getName, Student::getConsumption));studentMap1.forEach((key,value)->{System.out.println("key="+key+":"+"map"+value);});}/*将流中的元素实现数据库操作中组函数功能*/@Testpublic void test04(){//最大值Optional<Double> max = students.stream().map(Student::getConsumption).collect(Collectors.maxBy(Double::compareTo));System.out.println(max);//最小值Optional<Double> min = students.stream().map(Student::getConsumption).collect(Collectors.minBy(Double::compareTo));System.out.println(min);//求和Double sum = students.stream().collect(Collectors.summingDouble(Student::getConsumption));System.out.println(sum);//平均值Double averaging = students.stream().collect(Collectors.averagingDouble(Student::getConsumption));System.out.println(averaging);//计数Long count = students.stream().collect(Collectors.counting());System.out.println(count);//获得一个对该组数值进行操作的包装类,该包装类包含了组函数的操作DoubleSummaryStatistics doubleSummaryStatistics = students.stream().collect(Collectors.summarizingDouble(Student::getConsumption));System.out.println("-----------------");System.out.println(doubleSummaryStatistics.getMax());System.out.println(doubleSummaryStatistics.getAverage());}/*将流进行分组操作*/@Testpublic void test5(){Map<Student.Status, List<Student>> statusListMap = students.stream().collect(Collectors.groupingBy(Student::getStatus));System.out.println(statusListMap);}/*将流进行多级分组*/@Testpublic void test6(){Map<Student.Status, Map<String, List<Student>>> statusMapMap = students.stream().collect(Collectors.groupingBy(Student::getStatus, Collectors.groupingBy((student -> {if (student.getAge() < 20) {return "青年";} else if (student.getAge() < 30) {return "中年";} else {return "老年";}}))));System.out.println(statusMapMap);}/*分区*/@Testpublic void test7(){Map<Boolean, List<Student>> booleanMap = students.stream().collect(Collectors.partitioningBy(student -> student.getConsumption() > 2000));System.out.println(booleanMap);}/*Collections的拼接以及归约*/@Testpublic void test8(){//拼接:Collections.joining()String joinName = students.stream().map(Student::getName).collect(Collectors.joining(",", "{", "}"));System.out.println(joinName);//归约:Collections.reducing()Optional<Double> reduce = students.stream().map(Student::getConsumption).collect(Collectors.reducing(Double::sum));System.out.println(reduce);}}

Optional API

/** 一、Optional 容器类:用于尽量避免空指针异常*   Optional.of(T t) : 创建一个 Optional 实例*    Optional.empty() : 创建一个空的 Optional 实例*  Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例*    isPresent() : 判断是否包含值*  orElse(T t) :  如果调用对象包含值,返回该值,否则返回t*  orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值*    map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()*  flatMap(Function mapper):与 map 类似,要求返回值必须是Optional*/
public class TestOptional {@Testpublic void test01(){//Optional.of(T t)Optional<Student> op1 = Optional.of(new Student("xiaoming"));System.out.println(op1.get());//Optional.empty(),空Optional不能使用get方法NoSuchElementException异常,因为里面没有内置对象Optional<Object> empty = Optional.empty();System.out.println(empty);//Optional.ofNullable(T t)Optional<Object> op2 = Optional.ofNullable(null);System.out.println(op2);//isPresent()System.out.println(op2.isPresent()+"   and   "+empty.isPresent());//orElse(T t)System.out.println(op2.orElse(new Student("nihaoh")));//orElseGet(Supplier s)System.out.println(empty.orElseGet(()->{return new Student("woshi");}));//map(Function f)System.out.println(op1.map(Student::getName));//flatMap(Function mapper)System.out.println(op1.flatMap(student -> {return Optional.ofNullable(student.getName());}));}
}

提供了线程安全的时间类

关于JDK7时间类线程不安全的测试与解决方法

/*** 测试JDK1.7的时间类的线程安全,并在JDK1.7中解决*/
public class TestSimpleDateFormat {//JDk1.7时间类的线程安全@Testpublic void test1() throws Exception {SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy--MM--dd");Callable<Date> callable = new Callable() {@Overridepublic Date call() throws Exception {return dateFormat.parse("2001--09--16");}};//System.out.println(callable.call());//创建一个线程池ExecutorService pool = Executors.newFixedThreadPool(10);List<Future<Date>> result=new ArrayList<>();for (int i = 0; i < 10; i++) {result.add(pool.submit(callable));}for (Future<Date> future :result) {System.out.println(future.get());}pool.shutdown();//报错:java.util.concurrent.ExecutionException: java.lang.NumberFormatException: multiple points}//解决方案一@Testpublic void test02() throws ExecutionException, InterruptedException {//使用TreadLocal类包装要共享的变量SimpleDateFormatCallable<Date> callable = new Callable() {@Overridepublic Date call() throws Exception {return SimpleDateFormatThreadLocal.convert("2001--09--16");}};//System.out.println(callable.call());//创建一个线程池ExecutorService pool = Executors.newFixedThreadPool(10);List<Future<Date>> result=new ArrayList<>();for (int i = 0; i < 10; i++) {result.add(pool.submit(callable));}for (Future<Date> future :result) {System.out.println(future.get());}pool.shutdown();}//解决方案二:使用Java8中的线程安全的时间类@Testpublic void test03() throws Exception{DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy--MM--dd");Callable<LocalDate> callable = new Callable() {@Overridepublic LocalDate call() throws Exception {return LocalDate.parse("2001--09--16",dateTimeFormatter);}};//System.out.println(callable.call());//创建一个线程池ExecutorService pool = Executors.newFixedThreadPool(10);List<Future<LocalDate>> result=new ArrayList<>();for (int i = 0; i < 10; i++) {result.add(pool.submit(callable));}for (Future<LocalDate> future :result) {System.out.println(future.get());}pool.shutdown();}
}/*** TreadLocal类包装共享变量SimpleDateFormat*/
public class SimpleDateFormatThreadLocal{private static final ThreadLocal<DateFormat> local=new ThreadLocal<DateFormat>(){@Overrideprotected DateFormat initialValue() {return new SimpleDateFormat("yyyy--MM--dd");}};public static final Date convert(String srouce) throws ParseException {return local.get().parse(srouce);}
}

常用方法

//常用类与方法测试
public class mainTest1 {//LocalDate,LocalTime,LocalDateTime@Testpublic void test01(){//上述时间类都有一样的方法,分别代表的是:日期、时间、日期时间LocalDateTime now = LocalDateTime.now();//获取当前时间System.out.println(now);//获取指定日期的日期时间包装类LocalDateTime dateTime01 = LocalDateTime.of(2001, 9, 16, 0, 6);System.out.println(dateTime01);//对日期与时间的加减操作LocalDateTime dateTime02 = dateTime01.plusYears(3).minusYears(2);System.out.println(dateTime02);//获得日期时间包装类的具体某一项时间的值System.out.println(dateTime01.getDayOfMonth());System.out.println(dateTime01.getHour());System.out.println(dateTime01.getDayOfWeek());}//Instant : 时间戳。 (使用 Unix 元年  1970年1月1日 00:00:00 所经历的毫秒值)//默认使用的是UTC时区@Testpublic void test02(){Instant instant = Instant.now();System.out.println(instant);//运行的本机时间为16:45,打印时间为2021-11-16T08:44:10.596Z//ofHours(int hours)根据偏移时间,得到一个实例ZoneOffset。//中国的时区与UTC时区差了八个小时OffsetDateTime odt = instant.atOffset(ZoneOffset.ofHours(8));System.out.println(odt);//得到一个纳秒数System.out.println(instant.getNano());//914000000//ofEpochSecond(long epochSecond)获得由1970-01-01t00:00:00z时代偏移Long秒的Instant实例。Instant instant1 = Instant.ofEpochSecond(5);System.out.println(instant1);//1970-01-01T00:00:05Z}//Duration : 用于计算两个“时间”间隔//Period : 用于计算两个“日期”间隔(注意)@Testpublic void test03() throws InterruptedException {Instant ins1 = Instant.now();Thread.sleep(1000);Instant ins2 = Instant.now();System.out.println(Duration.between(ins1,ins2));System.out.println("-------------------");//Period.between只能算月份之内的数据,比如计算2020-04-21距离2021-02-22间隔的天数// 那么用Period.between来计算就是只有一天。// 计算间隔天数需要改成// ChronoUnit.DAYS.between(timeLocal, LocalDate.now());LocalDate now = LocalDate.now();LocalDate data = LocalDate.of(2021, 9, 16);Period period = Period.between(data,now);System.out.println(period);System.out.println(period.getYears());System.out.println(period.getDays());}//时间校正器:TemporalAdjuster@Testpublic void test04(){LocalDate date1 = LocalDate.now();System.out.println(date1);//将date1中的日期改为当月10号LocalDate date2 = date1.withDayOfMonth(10);System.out.println(date2);//使用校正器将date1的日期改为下一周的星期日LocalDate date3 = date1.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));System.out.println(date3);//自定义时间校正器,改为下个工作日LocalDate date5 = date1.with((date) -> {LocalDate date4 = (LocalDate) date;DayOfWeek dayOfWeek = date1.getDayOfWeek();if (dayOfWeek.equals(DayOfWeek.FRIDAY)) {return date4.plusDays(3);} else if (dayOfWeek.equals(DayOfWeek.SATURDAY)) {return date4.plusDays(2);} else {return date4.plusDays(1);}});System.out.println(date5);}//DateTimeFormatter:解析和格式化日期或时间@Testpublic void test5(){//默认的解析格式是:DateTimeFormatter.ISO_LOCAL_DATEDateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss E");LocalDateTime ldt = LocalDateTime.now();//按照dtf的格式格式成字符串String strDate = ldt.format(dtf);System.out.println(strDate);//将字符串日期按照dtf指定的格式解析成系统日期LocalDateTime newLdt = ldt.parse(strDate, dtf);System.out.println(newLdt);}//时区:ZoneId@Testpublic void test06(){//查看所有的时区//Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();//availableZoneIds.forEach(System.out::println);//将当前时间设置为指定时区的时间LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));System.out.println(now);//带时区的时间ZonedDateTime now1 = ZonedDateTime.now(ZoneId.of("US/Pacific"));System.out.println(now1);}
}

【JDK8语法新特性】:超全总结{lamda,stream,optional,新日期类API},JDK8对策略模式支持,可以直接贴代码运行测试。相关推荐

  1. JDK8新特性:Lambda表达式、Stream流、日期时间工具类

    重要特性: 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值. 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号. 可选的大括号:如果主体包含了一个语句,就不需要大括号. ...

  2. java8日期加本地,日期时间API(JDK8新增)

    日期时间API(JDK8新增) JDK8出现之前 JDK8新时间日期API LocalDate.LocalTime.LocalDateTime 的使用 类似于Calendar LocalDateTim ...

  3. ES6/ES7/ES8/ES9/ES10常用特性和新特性最全总结

    ES6 ES6在ES5的基础上新增了一系列特性,这里仅列出常用特性 变量的改变,添加了块级作用域的概念 let声明变量(块级作用域),let是更完美的var,它声明的全局变量不是全局属性widow的变 ...

  4. JDK1.8 新特性(全)

    JDK1.8 新特性 本文主要介绍了JDK1.8版本中的一些新特性,乃作者视频观后笔记,仅供参考. jdk1.8新特性知识点: Lambda表达式 函数式接口 方法引用和构造器调用 Stream AP ...

  5. Oracle 19c和20c新特性最全解密

    本期为我们带来分享的嘉宾是 ACOUG 核心专家,Oracle ACE 总监 杨廷琨先生,本次嘉年华上,杨老师为我们带来题为:Oracle 19c 和 20c 的新特性解密 主题分享.下面,让我们跟随 ...

  6. JDK8新特性(三):集合之 Stream 流式操作

    1.Stream流由来 首先我们应该知道:Stream流的出现,主要是用在集合的操作上.在我们日常的工作中,经常需要对集合中的元素进行相关操作.诸如:增加.删除.获取元素.遍历. 最典型的就是集合遍历 ...

  7. 傲游3.0.22.1000_Beta 10项新特性,超有料更新

    除了10多项新特性, 还有一些功能细节改进, 以及大量问题修正. 其中包括地址栏无法输入, 点击连接打开下载页面等用户反馈集中的问题. 这些新特性是: 全新Beta图标 支持自定义搜索栏, 头像等界面 ...

  8. html5用在什么领域,html5技术有哪些新特性(全方面了解html5特点)

    语义化就是让计算机能够快速读懂内容,高效的处理信息.搜索引擎只能通过标签来判断内容的语义,因为页面的很大一部分流量来自搜索引擎,要使页面尽可能地对搜索引擎友好,所以尽可能地使用语义化标签,如: div ...

  9. java stream api 对象复制_Java 8新特性之旅:使用Stream API处理集合

    在这篇"Java 8新特性教程"系列文章中,我们会深入解释,并通过代码来展示,如何通过流来遍历集合,如何从集合和数组来创建流,以及怎么聚合流的值. 在之前的文章"遍历.过 ...

最新文章

  1. flash,sdram 和 cpu 是 T形连接(类似于争的板子上flash和sdram的拓扑结构) --- FLASH搭上SDRAM,并不是你想象的那样不用布等长!...
  2. 图像修复中的TV模型
  3. vue-router之路由属性配置说明
  4. 我把这篇文章给女朋友看,她终于明白什么是「数据中台」了
  5. mysql不兼容_mysql5.7 不兼容问题
  6. 多媒体技术基础及应用
  7. Redis使用详细教程
  8. 高并发高可用高性能的解决方案
  9. 运用spss modeler运用支持向量机_使用支持向量回归进行Facebook股票预测
  10. matlab中几种取整函数的用法(fix, floor, ceil, round)
  11. 微信小程序 登陆过期,请重新授权
  12. YOLOv5 6.0 解决不显示Gflops方法:
  13. 《SRE:Google运维解密》读后有感
  14. 字符编码-带你走出Unicode与UTF-8的误区
  15. CS研究生学习阶段必读书籍
  16. MVP实现Recy多条目展示
  17. github项目下载单个文件夹的办法
  18. solidworks属性管理器_SOLIDWORKS BOM快捷生成第一步 | 完善产品属性
  19. 小白学机器学习西瓜书-第三章对数几率回归
  20. 最简易的js的按键组合

热门文章

  1. 《进击的虫师》爬取豆瓣电影海报(Top250)
  2. 萤火虫算法_40多种智能优化算法原理和代码分享
  3. StringBuffer详解
  4. 设计模式-迭代器模式
  5. django使用二——restful框架使用
  6. pr玩转特效的九大技巧
  7. c语言上机题库编程,全国二级C语言上机编程题库
  8. android Panel控件 抽屉控件
  9. Python 二维列表
  10. 短视频类APP盈利与开发模式个人拙见