JDK1.8新特性(剩余)【Stream;Optional;接口的类优先原则 和 接口冲突;日期时间组件 ;重复注解】--学习JavaEE的day43

本文主要是介绍JDK1.8新特性(剩余)【Stream;Optional;接口的类优先原则 和 接口冲突;日期时间组件 ;重复注解】--学习JavaEE的day43,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

day43

JDK1.8新特性

Stream

简介

Stream(流)是数据渠道,用于操作数据源(集合、数组等),生成元素序列。换言之,集合是存储数据的容器,流使用操作这些数据的

Stream可以对集合进行非常复杂的查找、过滤、映射数据等操作,类似于SQL执行数据库查询。Stream提供了一种高效且易于使用的处理数据的方式

注意:

  • Stream不会存储数据
  • Stream不会改变源数据,通过一系列操作数据源会返回一个持有结果的新Stream
  • Stream操作是延迟执行的,意味着流会等到需要结果的时候才执行
执行步骤
  1. 创建Stream:通过数据源(集合、数组等)获取一个Stream
  2. 中间操作:中间操作链,对源数据的数据进行处理
  3. 终止操作:执行中间操作,并产生结果
创建Stream
public class Test1 {@Testpublic void test01() {//方式一:通过Collection接口提供的stream()-串行流或parallelStream()-并行流 获取流对象List<String> list = new ArrayList<>();Stream<String> stream1 = list.stream();//方式二:通过Arrays的静态方法stream()获取流对象String[] strs = new String[10];Stream<String> stream2 = Arrays.stream(strs);//方式三:通过Stream的静态方法of()获取流对象Stream<String> stream3 = Stream.of("aaa","bbb","ccc");//方式四:创建无限流//iterate()迭代Stream<Integer> stream4 = Stream.iterate(1, (x)->x+=100);stream4.limit(3).forEach(System.out::println);//方式五:创建无限流Stream<Double> stream5 = Stream.generate(()->Math.random());stream5.limit(3).forEach(System.out::println);}
}

注意:多个中间操作可以连接成一个流水线,除非流水线触发终止操作,否则中间操作不会执行任何的处理,而在终止操作时一次性全部处理,称为惰性求值/延迟加载

中间操作 - 筛选与切片
方法描述
filter(Predicate p)从流中排除元素
limit(long maxSize)设置限制数据条数
skip(long n)跳过元素,返回跳过n个元素的流,若流中不满足n个元素则返回空流。与limit()互补
distinct()筛选,流通过元素对象的hashCode()和equals()方法去除重复元素

如果没有终止操作,中间操作就不会被调用,终止操作时一次性全部处理,这种称为惰性求值/延迟加载

public class Test1 {List<Student> stuList = Arrays.asList(new Student("张三", 28, 4800,Course.JAVA),new Student("李四", 36, 7200,Course.JAVA),new Student("王五", 19, 9600,Course.HTML),new Student("赵六", 42, 6100,Course.HTML),new Student("孙七", 23, 9600,Course.PYTHON),new Student("吴八", 31, 3000,Course.PYTHON),new Student("李四", 36, 7200,Course.JAVA));@Testpublic void test01() {	//需求1:过滤掉小于5000的学生对象Stream<Student> stream = stuList.stream().filter((x)-> {System.out.println("中间操作");return x.getSalary()>5000;});//迭代输出流里的数据就等同于终止操作//迭代功能在forEach()中完成,称为内部迭代(集合使用iterator()称为外部迭代)stream.forEach(System.out::println);}@Testpublic void test02() {	//需求2:过滤掉小于5000的学生对象,并显示3条//注意:因为限制了数据条数,所以满足数据条数后,后续的操作就不再运行了,效率就提高了Stream<Student> stream = stuList.stream().filter((x)-> {System.out.println("短路");return x.getSalary()>5000;}).limit(3);//迭代输出流里的数据就等同于终止操作//迭代功能在forEach()中完成,称为内部迭代(集合使用iterator()称为外部迭代)stream.forEach(System.out::println);}@Testpublic void test03() {	//需求3:过滤掉小于5000的学生对象,并跳过第1个学生对象Stream<Student> stream = stuList.stream().filter((x)-> x.getSalary()>5000).skip(1);//迭代输出流里的数据就等同于终止操作//迭代功能在forEach()中完成,称为内部迭代(集合使用iterator()称为外部迭代)stream.forEach(System.out::println);}@Testpublic void test04() {	//需求4:过滤掉小于5000的学生对象,并筛选掉重复元素//Stream底层通过元素对象(Student对象)的hashCode()和equals()方法去除重复元素Stream<Student> stream = stuList.stream().filter((x)-> x.getSalary()>5000).distinct();//迭代输出流里的数据就等同于终止操作//迭代功能在forEach()中完成,称为内部迭代(集合使用iterator()称为外部迭代)stream.forEach(System.out::println);}
}
enum Course{//课程枚举JAVA,HTML,PYTHON;
}
class Student{//学生类private String name;private int age;private double salary;private Course course;...
}
中间操作 - 映射
方法描述
map(Function<?, ? > mapper)将流中所有元素映射成一个新的元素或者提取信息
flatMap(Function<?, ? extends Stream<? >> mapper)将流中的流整合(整合成平面/平铺流)
public class Test1 {List<String> nameList = Arrays.asList("张三","李四","王五","赵六","孙七","吴八");	List<Student> stuList = Arrays.asList(new Student("张三", 28, 4800,Course.JAVA),new Student("李四", 36, 7200,Course.JAVA),new Student("王五", 19, 9600,Course.HTML),new Student("赵六", 42, 6100,Course.HTML),new Student("孙七", 23, 9600,Course.PYTHON),new Student("吴八", 31, 3000,Course.PYTHON),new Student("李四", 36, 7200,Course.JAVA));@Testpublic void test01() {	//map() - 将流中所有元素映射成一个新的元素 或者 提取信息//方式1:映射成一个新的元素//需求://需求:nameList获取流对象,打印出所有学生的姓氏nameList.stream().map((str)-> str.charAt(0)).forEach(System.out::println);//方式2:映射成提取信息//需求:把原来流中的学生对象替换成学生姓名stuList.stream().map((stu)-> stu.getName()).forEach(System.out::println);}@Testpublic void test02() {	//带着需求学flatMap()//flatMap() - 将流中的流整合(整合成平面/平铺流)//需求:将nameList里的字符串转换为字符输出//解决方案1:使用map()完成需求,可以看到流里包含另外的流,非常麻烦Stream<Stream<Character>> stream = nameList.stream().map(Test1::getCharacterStream);//{{'张','三'},{'李','四'},...}stream.forEach((sm) -> {sm.forEach(System.out::println);});//解决方案2:使用flatMap()完成需求,将流中的流一并整合nameList.stream().flatMap((str)-> getCharacterStream(str)).forEach(System.out::println);//{'张','三'},{'李','四'},...}//将字符串拆分出字符转换为流的方法public static Stream<Character> getCharacterStream(String str){ArrayList<Character> list = new ArrayList<>();for (Character c : str.toCharArray()) {list.add(c);}return list.stream();}
}
enum Course{//课程枚举JAVA,HTML,PYTHON;
}
class Student{//学生类private String name;private int age;private double salary;private Course course;...
}

继day42

中间操作 - 排序
方法解释
sorted()使用元素原有排序规则 - Comparable
sorted(Comparator<? super T> comparator)使用自定义排序规则 - Comparator

不同条件排序,不同比较器,涉及前面比较器内容

public class Test01 {List<Student> stuList = Arrays.asList(new Student("张三", 28, 4800,Course.JAVA),new Student("李四", 36, 7200,Course.JAVA),new Student("王五", 19, 9600,Course.HTML),new Student("赵六", 42, 6100,Course.HTML),new Student("孙七", 23, 9600,Course.PYTHON),new Student("吴八", 31, 3000,Course.PYTHON),new Student("吴八", 31, 3000,Course.PYTHON));@Testpublic void test01(){//需求:按照年龄排序 -- 内置比较器stuList.stream().sorted().forEach(System.out::println);}@Testpublic void test02(){//需求:按照工资排序 -- 外置比较器stuList.stream().sorted((stu1,stu2)->{return Double.compare(stu1.getSalary(), stu2.getSalary());}).forEach(System.out::println);}}
enum Course{//课程枚举JAVA,HTML,PYTHON;
}
class Student implements Comparable<Student>{//学生类private String name;private int age;private double salary;...
}
终止操作 - 匹配与查找
方法描述
allMatch(Predicate<? super T> predicate)检查是否匹配所有元素
anyMatch(Predicate<? super T> predicate)检查是否匹配至少一个元素
noneMatch(Predicate<? super T> predicate)检查是否没有匹配所有元素
findFirst()返回第一个元素
findAny()返回任意一个元素(但效果不好)
count()返回流中元素的个数
max(Comparator<? super T> comparator)返回流中最大值
min(Comparator<? super T> comparator)返回流中最小值

所有终止操作都有返回值
匹配查找:使用方法有所差别

public class Test02 {List<Student> stuList = Arrays.asList(new Student("张三", 28, 4800,Course.JAVA),new Student("李四", 36, 7200,Course.JAVA),new Student("王五", 19, 9600,Course.HTML),new Student("赵六", 42, 6100,Course.HTML),new Student("孙七", 23, 9600,Course.PYTHON),new Student("吴八", 31, 3000,Course.PYTHON),new Student("吴八", 31, 3000,Course.PYTHON));@Testpublic void test01(){//需求1:检查流中素所有元素是否匹配工资>5000boolean bool = stuList.stream().allMatch((stu)->{if(stu.getSalary() > 5000){return true;}return false;});System.out.println(bool);}@Testpublic void test02(){//需求2:检查流中素所有元素至少匹配一个工资>5000boolean bool = stuList.stream().anyMatch((stu)->{if(stu.getSalary() > 5000){return true;}return false;});System.out.println(bool);}@Testpublic void test03(){//需求3:检查流中素所有元素是否没有匹配 工资>5000boolean bool = stuList.stream().noneMatch((stu)->{if(stu.getSalary() > 5000){return true;}return false;});System.out.println(bool);}@Testpublic void test04(){//需求4:返回工资最高的学生信息Optional<Student> optional = stuList.stream().sorted((stu1,stu2)->{return Double.compare(stu2.getSalary(), stu1.getSalary());}).findFirst();Student stu = optional.get();System.out.println(stu);}@Testpublic void test05(){//需求5:返回随机学生信息(但效果不好)Optional<Student> optional = stuList.stream().findAny();Student stu = optional.get();System.out.println(stu);}@Testpublic void test06(){//需求6:获取学生个数long count = stuList.stream().count();System.out.println(count);}@Testpublic void test07(){//需求7:获取最高工资的学生信息Optional<Student> optional = stuList.stream().max((stu1,stu2)->Double.compare(stu1.getSalary(), stu2.getSalary()));Student stu = optional.get();System.out.println(stu);}@Testpublic void test08(){//需求8:获取最低工资的学生信息Optional<Student> optional = stuList.stream().min((stu1,stu2)->Double.compare(stu1.getSalary(), stu2.getSalary()));Student stu = optional.get();System.out.println(stu);}
}enum Course{//课程枚举JAVA,HTML,PYTHON;
}
class Student implements Comparable<Student>{//学生类private String name;private int age;private double salary;private Course course;...
}
终止操作 - 归约

归约:将流中的元素反复结合起来,得到一个值

map+reduce的连接通常称为map_reduce模式,因Google用它进行网络搜索而出名

方法描述
reduce( T identity , BinaryOperator accumulator)参数:(初始值,结合逻辑)
reduce(BinaryOperator accumulator)参数:(结合逻辑)
public class Test03 {List<Integer> numList = Arrays.asList(1,2,3,4,5,6,7,8,9,10);List<Student> stuList = Arrays.asList(new Student("张三", 28, 4800,Course.JAVA),new Student("李四", 36, 7200,Course.JAVA),new Student("王五", 19, 9600,Course.HTML),new Student("赵六", 42, 6100,Course.HTML),new Student("孙七", 23, 9600,Course.PYTHON),new Student("吴八", 31, 3000,Course.PYTHON),new Student("吴八", 31, 3000,Course.PYTHON));@Testpublic void test01(){//需求1:获取numList集合中元素的总和Integer sum = numList.stream().reduce(0, (x,y)->x+y);System.out.println(sum);}@Testpublic void test02(){//需求2:获取stuList集合中所有学生工资总和Optional<Double> optional = stuList.stream().map(Student::getSalary).reduce(Double::sum);Double sum = optional.get();System.out.println(sum);}}
enum Course{//课程枚举JAVA,HTML,PYTHON;
}
class Student implements Comparable<Student>{//学生类private String name;private int age;private double salary;private Course course;
终止操作 - 收集

收集:将流转换为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法

方法描述
collect(Collector<? super T, A, R> collector)把元素放入Collector集合中

补充:

收集比较麻烦
下面所做映射只能拿到单独的信息,获取更多信息就不用映射

注意方法的使用,有些方法不熟悉就查API,ps:

分组注意方法选择【提示输入时】【多重分组】
joining有很多重载的方法【方法参数(”分隔符“,“前缀或后缀”)】

public class Test04 {List<Student> stuList = Arrays.asList(new Student("张三", 28, 4800,Course.JAVA),new Student("李四", 36, 7200,Course.JAVA),new Student("王五", 19, 9600,Course.HTML),new Student("赵六", 42, 6100,Course.HTML),new Student("孙七", 23, 9600,Course.PYTHON),new Student("吴八", 31, 3000,Course.PYTHON),new Student("吴八", 31, 3000,Course.PYTHON));//将Stream中的数据收集到集合中----------------------------------------------------------@Testpublic void test01(){//将Stream中的数据收集到List集合中List<Student> list = stuList.stream().collect(Collectors.toList());for (Student stu : list) {System.out.println(stu);}}@Testpublic void test02(){//将Stream中的数据收集到List集合中Set<Student> set = stuList.stream().collect(Collectors.toSet());for (Student stu : set) {System.out.println(stu);}}@Testpublic void test03(){//将Stream中的数据收集到指定集合中LinkedList<Student> linkedList = stuList.stream().collect(Collectors.toCollection(LinkedList::new));for (Student stu : linkedList) {System.out.println(stu);}}//收集流中各种数据 ----------------------------------------------------------@Testpublic void test04(){//需求1:收集/获取学生个数Long count = stuList.stream().collect(Collectors.counting());System.out.println(count);}@Testpublic void test05(){//需求2:收集/获取学生平均工资Double avg = stuList.stream().collect(Collectors.averagingDouble(Student::getSalary));System.out.println(avg);}@Testpublic void test06(){//需求3:收集/获取学生总工资Double sum = stuList.stream().collect(Collectors.summingDouble(Student::getSalary));System.out.println(sum);}@Testpublic void test07(){//需求4:收集/获取学生工资最大值Optional<Double> optional = stuList.stream().map(Student::getSalary).collect(Collectors.maxBy(Double::compareTo));Double max = optional.get();System.out.println(max);}@Testpublic void test08(){//需求5:收集/获取学生工资最小值Optional<Double> optional = stuList.stream().map(Student::getSalary).collect(Collectors.minBy(Double::compareTo));Double min = optional.get();System.out.println(min);}@Testpublic void test09(){//需求6:收集/获取工资最多的学生信息Optional<Student> optional = stuList.stream().collect(Collectors.maxBy((stu1,stu2)->{return Double.compare(stu1.getSalary(), stu2.getSalary());}));Student stu = optional.get();System.out.println(stu);}@Testpublic void test10(){//需求7:收集/获取工资最少的学生信息Optional<Student> optional = stuList.stream().collect(Collectors.minBy((stu1,stu2)->{return Double.compare(stu1.getSalary(), stu2.getSalary());}));Student stu = optional.get();System.out.println(stu);}//分组收集 ----------------------------------------------------------@Testpublic void test11(){//需求:按照学科分组Map<Course, List<Student>> map = stuList.stream().collect(Collectors.groupingBy(Student::getCourse));Set<Entry<Course,List<Student>>> entrySet = map.entrySet();for (Entry<Course, List<Student>> entry : entrySet) {System.out.println(entry);}}@Testpublic void test12(){//需求:按照学科分组,在按照年龄分组Map<Course, Map<String, List<Student>>> map = stuList.stream().collect(Collectors.groupingBy(Student::getCourse, Collectors.groupingBy((stu)->{if(((Student)stu).getAge() < 28){return "青年";}else if(((Student)stu).getAge() < 40){return "中年";}else{return "老年";}})));Set<Entry<Course,Map<String,List<Student>>>> entrySet = map.entrySet();for (Entry<Course, Map<String, List<Student>>> entry : entrySet) {Course course = entry.getKey();System.out.println(course);Map<String, List<Student>> value = entry.getValue();Set<Entry<String,List<Student>>> entrySet2 = value.entrySet();for (Entry<String, List<Student>> entry2 : entrySet2) {String key = entry2.getKey();List<Student> value2 = entry2.getValue();System.out.println(key + " -- " + value2);}}}//分区收集 ----------------------------------------------------------@Testpublic void test13(){//需求:按照工资5000为标准分区Map<Boolean, List<Student>> map = stuList.stream().collect(Collectors.partitioningBy((stu)->{if(stu.getSalary() > 5000){return true;}return false;}));Set<Entry<Boolean,List<Student>>> entrySet = map.entrySet();for (Entry<Boolean, List<Student>> entry : entrySet) {System.out.println(entry);}}//获取元素中字段的各种信息  ----------------------------------------------------------@Testpublic void test14(){//需求:获取学生工资信息,再获取总值、平均值、最大值、最小值DoubleSummaryStatistics dss = stuList.stream().collect(Collectors.summarizingDouble(Student::getSalary));System.out.println("总值:" + dss.getSum());System.out.println("平均值:" + dss.getAverage());System.out.println("最大值:" + dss.getMax());System.out.println("最小值:" + dss.getMin());}//拼接信息  ----------------------------------------------------------@Testpublic void test15(){//需求:拼接学生姓名String str = stuList.stream().map(Student::getName).collect(Collectors.joining());System.out.println(str);}@Testpublic void test16(){//需求:拼接学生姓名String str = stuList.stream().map(Student::getName).collect(Collectors.joining("--"));System.out.println(str);}@Testpublic void test17(){//需求:拼接学生姓名String str = stuList.stream().map(Student::getName).collect(Collectors.joining("--", "aa", "bb"));System.out.println(str);}
}enum Course{//课程枚举JAVA,HTML,PYTHON;
}
class Student implements Comparable<Student>{//学生类private String name;private int age;private double salary;private Course course;...
}

并行流与串行流

并行流就是把一个内容拆分成多个数据块,并用不同的线程分别处理每个数据块的流。Java8中将并行进行了优化,我们可以很容易的对数据进行并行操作。Stream API可以声明性地通过 parallel() - 并行流 与sequential()-顺序流 之间进行切换。

注意

  1. 默认为顺序流/串行流
  2. 并行流一般在大数据搜索里使用到
  3. JDK1.8之前也有并行流,叫做Fork/Join并行计算框架
public class Test05 {public static void main(String[] args) {//需求:使用并行流计算1-10000000L之和OptionalLong optionalLong = LongStream.range(1, 10000001L).生成1-10000000的数流parallel().//设置成并行流reduce(Long::sum);//归约求总值long sum = optionalLong.getAsLong();System.out.println(sum);}
}

Optional

Optional类(java. util. Optional)是一个容器类,代表一个存在或不存在的值,原来用null表示一个值不

存在,现在Optional可以更好的表达这个概念。并且可以避免空指针异常

此类的设计就是更好的避免空指针异常

方法描述
Optional.of(T t)创建一个Optional实例
Optional.empty()创建一 个空的 Optional实例
Optional.ofNullable(T t)若t不为null,创建Optional实例,否则创建空实例
get()获取Optional实例里的对象
isPresent()判断是否包含值
orElse(T t)如果调用对象包含值, 返回该值,否则返回t
orElseGet(Supplier s)如果调用对象包含值,返回该值,否则返回s获取的值
map(Function f)如果有值对其处理,并返回处理后的Optional,否则返回optional. empty()
flatMap(Function mapper)与map 类似,要求返回值必须是Optional

map返回的值可以是任意类型

public class Test01 {public static void main(String[] args) {//将数据添加到Optional对象中//Optional<String> optional = Optional.of("aaabbb");//创建空内容的Optional对象Optional<String> optional = Optional.empty();method(optional);}public static void method(Optional<String> optional){//获取Optional对象中的数据//String str = optional.get();//获取Optional对象中的数据,如果没有数据就返回默认值String str = optional.orElse("默认值");System.out.println(str);}}
public class Test02 {@Testpublic void test01() {//创建一个Optional实例,把对象封装到Optional容器里
//		Optional<Student> op = Optional.of(new Student("aaa", 26, 6666, Course.HTML));//创建一个空的Optional容器
//		Optional<Student> op = Optional.empty();//创建一个Optional实例,若对象为null->创建空实例,若对象为不为null->创建Optional实例Optional<Student> op = Optional.ofNullable(new Student("bbb", 26, 7777, Course.PYTHON));//判断容器里是否包含对象if(op.isPresent()){//包含System.out.println("获取容器里的对象:" + op.get().getName());}else{//不包含System.out.println("容器里的对象为null");}//如果容器里有对象就返回,否则就返回新对象Student stu = op.orElse(new Student("ccc", 26, 8888, Course.JAVA));System.out.println(stu.getName());//不同情况下可以返回不同对象,orElseGet()比orElse()可变性更强boolean bool = true;stu = op.orElseGet(()->{if(bool){return new Student("吴彦祖", 26, 8888, Course.JAVA);}else{return new Student("麻生希", 26, 8888, Course.JAVA);}});//获取原容器中的某个值并返回新容器中//map(Function<? super T, ? extends U> mapper)Optional<String> map = op.map(Student::getName);System.out.println(map.get());//与map 类似,要求返回值必须是Optional//flatMap(Function<? super T, Optional<U>> mapper)Optional<String> flatMap = op.flatMap((e)->Optional.of(e.getName()));System.out.println(flatMap.get());}
}enum Course{//课程枚举JAVA,HTML,PYTHON;
}
class Student implements Comparable<Student>{//学生类private String name;private int age;private double salary;private Course course;...
}

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

从JDK1.8开始,接口中可以有默认方法,既default修饰的方法,此方法可以让接口的实现类所调用,而接

口中的静态方法直接用接口名调用即可

public class Test1 {@Testpublic void test01() {MyClass myClass = new MyClass();myClass.defaultMethod();I1.staticMethod();}
}
interface I1{default void defaultMethod(){System.out.println("接口中的默认方法");}public static void staticMethod(){System.out.println("接口中的静态方法");}
}
class MyClass implements I1{}

接口默认方法的”类优先”原则:

  • 如果一个接口中定义了一个默认方法,而接口实现类的父类定义了一个同名的方法时,选择父类中的方法

  • 接口冲突:如果一个父接口提供一个默认方法,而另一个接口也提供了一个具有相同名称和参数列表的方法(不管方法是否是默认方法),那么必须覆盖该方法来解决冲突

public class Test01 {public static void main(String[] args) {B b = new B();b.method();}
}
interface I1{default void method(){System.out.println("I1接口中的method方法");}
}
class A{public void method(){System.out.println("A类中的method方法");}
}
class B extends A implements I1{}
public class Test01 {public static void main(String[] args) {}
}
interface I1{default void method(){}
}
interface I2 extends I1{public void method();
}
class A implements I2{@Overridepublic void method() {}
}

日期组件

JDK1.8提供的新日期类都是不可变的,既不管怎么样的改变,都会产生一个新的实例,他们都是线程安全的

日期组件遵循与IOS-8601世界时间标准

组件简介
包路径类名描述
java.time针对日期和时间操作的包
LocalDate用于表示日期的类
LocalTime用于表示时间的类
LocalDateTime用于表示日期时间的类
Instant时间戳类(1970.1.1 0:0:0 到现在的毫秒数)
Period两个日期间隔类
Duration两个时间间隔类
java.time.chrono针对日期时间特殊格式操作的包
JapaneseChronology日本帝国历法系统类
ThaiBuddhistChronology泰国佛教日历系统类
java.time.format针对时间日期时间格式化操作的包
DateTimeFormatter格式化日期时间类
java.time.temporal针对时间矫正操作的包
java.time.zone针对时区操作的包
日期时间类、时间戳、间隔类
public class Test01 {@Testpublic void test01() {//LocalDate LocalTime LocalDateTime//这三个日期类的使用大致一样//获取当前日期时间对象LocalDateTime ldt1 = LocalDateTime.now();System.out.println(ldt1);//2024-4-27T11:16:30.786//获取指定日期时间对象LocalDateTime ldt2 = LocalDateTime.of(2024, 1, 23, 8, 30, 10, 10);System.out.println(ldt2);//2024-1-23T8:30:10.000000010//获取ldt1推后的时间日期对象LocalDateTime ldt3 = ldt1.plusYears(2);System.out.println(ldt3);//2026-4-27T11:16:30.786//获取ldt1提前的时间日期对象LocalDateTime ldt4 = ldt3.minusMonths(2);//2026-2-27T11:16:30.786//获取单个日期信息System.out.println(ldt4.getYear());System.out.println(ldt4.getMonthValue());System.out.println(ldt4.getDayOfMonth());System.out.println(ldt4.getHour());System.out.println(ldt4.getMinute());System.out.println(ldt4.getSecond());}@Testpublic void test02() {//使用时间戳(从1970年1月1日0:0:0到现在的毫秒值)//默认创建UTC(世界标准时间)时区的时间戳对象Instant now1 = Instant.now();System.out.println(now1);//2024-04-27T03:19:19.352Z//获取偏移8小时的偏移日期时间对象OffsetDateTime odt = now1.atOffset(ZoneOffset.ofHours(8));System.out.println(odt);//2024-04-27T11:19:19.352+08:00//获取时间戳的毫秒值形式System.out.println(now1.toEpochMilli());//1714187959352//获取一个1970年1月1日0:0:0 往后退1秒的时间戳对象Instant now2 = Instant.ofEpochSecond(1);System.out.println(now2);//1970-01-01T00:00:01Z}@Testpublic void test03() throws InterruptedException {//Duration:时间间隔类Instant now1 = Instant.now();Thread.sleep(1000);Instant now2 = Instant.now();//获取时间间隔类对象Duration duration1 = Duration.between(now1, now2);System.out.println(duration1.toMillis());//1005System.out.println("-----------------------------");LocalTime lt1 = LocalTime.now();Thread.sleep(1000);LocalTime lt2 = LocalTime.now();//获取时间间隔类对象Duration duration2 = Duration.between(lt1, lt2);System.out.println(duration2.toMillis());//1013}@Testpublic void test04() throws InterruptedException {//Period:日期间隔类LocalDate ld1 = LocalDate.now();Thread.sleep(1000);LocalDate ld2 = LocalDate.of(2025, 12, 31);Period period = Period.between(ld1, ld2);System.out.println(period.getYears());//1System.out.println(period.getMonths());//8System.out.println(period.getDays());//4}
}
日期时间格式化类-DateTimeFormatter
public class Test02 {@Testpublic void test01() {//格式化日期时间类LocalDateTime ldt1 = LocalDateTime.now();//2024-04-27T11:25:19.091//获取本地标准的日期时间格式化对象DateTimeFormatter dtf1 = DateTimeFormatter.ISO_LOCAL_DATE_TIME;String strDateTime1 = ldt1.format(dtf1);//格式化时间日期System.out.println(strDateTime1);//2024-04-27T11:25:19.091//自定义日期时间格式化对象DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");String strDateTime2 = ldt1.format(dtf2);//格式化时间日期System.out.println(strDateTime2);//2024年04月27日 11:25:19//将指定格式的字符串解析成LocalDateTime对象LocalDateTime parse = LocalDateTime.parse("2024年04月27日 11:25:19", dtf2);System.out.println(parse);//2020-03-12T11:04:14}
}
时间矫正器类-TemporalAdjuster
public class Test03 {@Testpublic void test01() {//时间矫正器LocalDateTime ldt1 = LocalDateTime.now();//2024-04-27T11:25:19.091//设置指定月份LocalDateTime ldt2 = ldt1.withMonth(10);System.out.println(ldt2);//2024-10-27T11:25:19.091//设置下一个周末LocalDateTime ldt3 = ldt1.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));System.out.println(ldt3);//2024-04-28T11:27:41.517//自定义时间矫正器:设置下一个工作LocalDateTime ldt4 = ldt1.with((temporal)->{LocalDateTime ldt = (LocalDateTime) temporal;DayOfWeek week = ldt.getDayOfWeek();if(week.equals(DayOfWeek.FRIDAY)){//周五return ldt.plusDays(3);//往后推3天}else if(week.equals(DayOfWeek.SATURDAY)){//周六return ldt.plusDays(2);//往后推2天}else{return ldt.plusDays(1);//往后推1天}});System.out.println(ldt4);//2024-04-29T11:28:55.733}
}
时区类
public class Test04 {@Testpublic void test01() {//时区类 //获取所有时区字符串Set<String> set = ZoneId.getAvailableZoneIds();for (String str : set) {System.out.println(str);}System.out.println("---------------------------");//获取指定时区的日期时间对象LocalDateTime ldt1 = LocalDateTime.now(ZoneId.of("Asia/Tokyo"));System.out.println(ldt1);//2024-04-27T12:30:53.943System.out.println("---------------------------");//获取指定时区的日期时间对象 + 偏移量LocalDateTime ldt2 = LocalDateTime.now(ZoneId.of("Asia/Tokyo"));ZonedDateTime zonedDateTime = ldt2.atZone(ZoneId.of("Asia/Tokyo"));System.out.println(zonedDateTime);//2024-04-27T12:30:53.943+09:00[Asia/Tokyo]}
}

重复注解及类型注解

jdk1.8开始可以重复注解

ps:一个类可有多个同样的注解

@Author(name="张老师")
@Author(name="李老师")
public class Test01 {public static void main(String[] args) throws NoSuchMethodException, SecurityException {Class<?> clazz = Test01.class;//获取类上的注解Author[] as = clazz.getDeclaredAnnotationsByType(Author.class);for (Author author : as) {System.out.println(author.name());}//获取参数上的注解Method method = clazz.getMethod("method", String.class);Parameter[] parameters = method.getParameters();for (Parameter parameter : parameters) {Author annotation = parameter.getAnnotation(Author.class);System.out.println(annotation.name());}}public void method(@Author(name="何老师") String str){}
}//作者容器注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Authors {Author[] value();
}//作者注解
@Repeatable(Authors.class)//使用重复注解,就必须加上该注解
@Target({ElementType.TYPE,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Author {String name();
}

总结

1.Stream的中间操作 - 排序

2.Stream的终止操作 – 匹配与查找

3.Stream的终止操作 – 归约

4.Stream的终止操作 – 收集

5.Stream的串行流和并行流

6.Optional

7.接口的类优先原则 和 接口冲突

8.日期时间组件

9.重复注解

这篇关于JDK1.8新特性(剩余)【Stream;Optional;接口的类优先原则 和 接口冲突;日期时间组件 ;重复注解】--学习JavaEE的day43的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/944789

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

一篇文章彻底搞懂macOS如何决定java环境

《一篇文章彻底搞懂macOS如何决定java环境》MacOS作为一个功能强大的操作系统,为开发者提供了丰富的开发工具和框架,下面:本文主要介绍macOS如何决定java环境的相关资料,文中通过代码... 目录方法一:使用 which命令方法二:使用 Java_home工具(Apple 官方推荐)那问题来了,

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

Java中的.close()举例详解

《Java中的.close()举例详解》.close()方法只适用于通过window.open()打开的弹出窗口,对于浏览器的主窗口,如果没有得到用户允许是不能关闭的,:本文主要介绍Java中的.... 目录当你遇到以下三种情况时,一定要记得使用 .close():用法作用举例如何判断代码中的 input

Spring Gateway动态路由实现方案

《SpringGateway动态路由实现方案》本文主要介绍了SpringGateway动态路由实现方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随... 目录前沿何为路由RouteDefinitionRouteLocator工作流程动态路由实现尾巴前沿S