当前位置: 首页 > news >正文

Java8新特性学习

Java8新特性学习

  • 为啥使用Lambda表达式
    • Lambda表达式的基础语法
      • 无参无返回
      • 有参无返回
      • 一个参数
      • 多参
      • 单个语句体
      • 类型推断
  • 四大内置核心函数式接口
    • 其他接口
  • 方法引用与构造器引用
  • Stream
    • 简介
    • 什么是Stream
    • Stream操作步骤
      • 创建Stream
      • 中间操作
      • 终止操作(终端操作)
      • 归约与收集
  • 并行流与顺序流
    • Fork/Join框架
  • Optional类
  • 接口中的默认方法与静态方法
  • 时间和日期
    • 传统时间格式化
    • jdk8中的日期
  • 时间校正器
  • 时区的处理
  • 重复注解与类型注解

为啥使用Lambda表达式

Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(将代码 像数据一样进行传递)。可以写出更简洁、更 灵活的代码。作为一种更紧凑的代码风格,使 Java的语言表达能力得到了提升。

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> comparator = (x, y) -> {System.out.println("函数式接口");return Integer.compare(x, y);
};

单个语句体

语法格式五:若Lambda体中只有一条语句,return和大括号都可以省略不写

 Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);

类型推断

语法格式六:Lambda表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即"类型推断"

Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);

上联:左右遇一括号省
下联:左侧推断类型省
横批:能省则省
二、Lambda 表达式需要“函数式接口”的支持
函数式接口:接口中只有一个抽象方法的接口,称为函数式接口。可以使用注解@FunctionalInterface 修饰可以检查是否是函数式接口

package com.company;import org.junit.Test;import java.util.Comparator;
import java.util.function.Consumer;/*** @author Helen* @version 1.0* @createTime 2023/1/3 23:02* @Description Lambda基础语法*/
public class TestLambda2 {/*** 语法格式一: 无参数,无返回值*/@Testpublic void test() {Runnable runnable = () -> System.out.println("Hello Lambda!");runnable.run();}/*** 语法格式二:有一个参数,并且无返回值*/@Testpublic void test2() {Consumer consumer = (x) -> System.out.println(x);consumer.accept("我是上柜");}/*** 语法格式三 : 若只有一个参数,小括号可以省略不写*/@Testpublic void test3() {Consumer consumer = x -> System.out.println(x);consumer.accept("我是上柜");}/*** 语法格式四:有两个以上的参数,并且Lambda体中有多条语句*/@Testpublic void test4() {Comparator<Integer> comparator = (x, y) -> {System.out.println("函数式接口");return Integer.compare(x, y);};}/*** 语法格式五:若Lambda体中只有一条语句,return和大括号都可以省略不写*/@Testpublic void test5() {Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);}/*** 语法格式六:Lambda表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即"类型推断"*/@Testpublic void test6() {Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);}
}

四大内置核心函数式接口

在这里插入图片描述

package com.company;import org.junit.Test;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;/*** @author Helen* @version 1.0* @createTime 2023/1/3 23:38* @Description 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 TestLambda3 {/*** Predicate<T>:断言型接口*/@Testpublic void test4() {List<String> list= Arrays.asList("Hello","java","Lambda");List<String> stringList=filterStr(list,(s)->s.length()>4);System.out.println(stringList);}public List<String> filterStr(List<String> list, Predicate<String> predicate) {List<String> strList = new ArrayList<>();for (String str : list) {if (predicate.test(str)) {strList.add(str);}}return strList;}/*** Function<T,R>:函数型接口*/@Testpublic void test3() {String newStr = strHandler("\t\t\t 我要吃饭了", (str) -> str.trim());System.out.println(newStr);}/*** 用于处理字符串** @return*/public String strHandler(String str, Function<String, String> function) {return function.apply(str);}/*** Supplier<T>:供给型接口*/@Testpublic void test2() {List<Integer> list = getNumList(5, () -> (int) (Math.random() * 100));System.out.println(list);}public List<Integer> getNumList(int num, Supplier<Integer> sup) {List<Integer> list = new ArrayList<>();for (int i = 0; i < num; i++) {Integer n = sup.get();list.add(n);}return list;}/*** Consumer<T> :消费型接口*/@Testpublic void test1() {happy(10000, m -> System.out.println(m));}public void happy(double money, Consumer<Double> consumer) {consumer.accept(money);}
}

其他接口

在这里插入图片描述

方法引用与构造器引用

package com.company;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** @author Helen* @version 1.0* @createTime 2023/2/5 16:32* @Description*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee implements Serializable {private static final long serialVersionUID = 1L;private String name;
}
package com.company;import org.junit.Test;import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;/*** @author Helen* @version 1.0* @createTime 2023/2/1 22:41* @Description 方法引用* 方法引用:若Lambda 体中的内容有方法已经实现了,我们可以使用“方法引用”* (可以理解为方法引用是Lambda表达式的另外一种表现形式)* 主要有三种语法格式:* 对象::实例方法名* 类::静态方法名* 类::实例方法名* 注意:* ①Lambda 体中调用方法的参数列表与返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致!* ②若Lambda 参数列表中的第一参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以使用ClassName::method* <p>* 二、构造器引用:* <p>* 格式:* ClassName::new* 注意:需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致!* <p>* 三、数组引用* Type[]::new;*/
public class TestMethodRef {/*** 数组引用*/@Testpublic void test7() {Function<Integer, String[]> fun = (x) -> new String[x];String[] strs = fun.apply(10);System.out.println(strs.length);}@Testpublic void test6() {Function<String, Employee> function = (x) -> new Employee(x);// Employee只有一个有参构造器Function<String, Employee> fun2 = Employee::new;Employee employee = fun2.apply("小红");System.out.println(employee);}/*** 构造器引用*/@Testpublic void test5() {Supplier<Employee> supplier = () -> new Employee();// 构造器引用方式Supplier<Employee> supplier2 = Employee::new;Employee employee = supplier2.get();System.out.println(employee);}/*** 类::实例方法名*/@Testpublic void test4() {BiPredicate<String, String> biPredicate = (x, y) -> x.equals(y);BiPredicate<String, String> bp = String::equals;}/*** 类 :: 静态方法名*/@Testpublic void test3() {Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);Comparator<Integer> com = Integer::compare;}/*** 对象 ::实例方法名*/@Testpublic void test1() {PrintStream ps1 = System.out;Consumer<String> con = (x) -> ps1.println(x);PrintStream ps = System.out;Consumer<String> con1 = ps::println;Consumer<String> con2 = System.out::println;con2.accept("acdef");}@Testpublic void test2() {Employee emp = new Employee();Supplier<String> sup = () -> emp.getName();String str = sup.get();System.out.println(str);}
}

Stream

简介

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

什么是Stream

是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
“集合讲的是数据,流讲的是计算!”
注意:

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

Stream操作步骤

创建Stream

一个数据源(如:集合、数组),获取一个流

package com.company;import org.junit.Test;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;/*** Stream操作步骤* 1.创建Stream* 2.中间操作* 3.终止操作(终端操作)*/
public class TestStreamAPI {// 创建Stream@Testpublic void test1() {//1.可以通过Collection 系列集合提供的stream()或parallelStream()List<String> list = new ArrayList<>();Stream<String> stream1 = list.stream();// 2.通过Arrays 中的静态方法stream()获取数组流Employee[] employee = new Employee[10];Stream<Employee> stream2 = Arrays.stream(employee);// 3.通过Stream类中的静态方法of()Stream<String> stream3 = Stream.of("aa", "bb", "cc", "dd", "ee");//4。创建无限流//迭代Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);stream4.limit(10).forEach(System.out::println);//生成Stream.generate(()->Math.random()).limit(5).forEach(System.out::println);}
}

中间操作

一个中间操作链,对数据源的数据进行处理
在这里插入图片描述

package com.company;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** @author Helen* @version 1.0* @createTime 2023/2/5 16:32* @Description*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee implements Serializable {private static final long serialVersionUID = 1L;private String name;private Integer age;private Double salary;
}
package com.company;import org.junit.Test;import java.util.*;
import java.util.stream.Stream;/****/
public class TestStreamAPI2 {List<Employee> employees = Arrays.asList(new Employee("张三", 18, 9999.99),new Employee("李四", 58, 5555.55),new Employee("王五", 26, 3333.33),new Employee("赵六", 36, 6666.66),new Employee("田七", 12, 8888.88),new Employee("田七", 12, 8888.88),new Employee("田七", 12, 8888.88));/*** 筛选与切片* filter—接收Lambda,从流中排除某些元素* limit—截断流,使其元素不超过给定数量。* skip(n)—跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。* 与limit(n)互补 distinct一—筛选,通过流所生成元素的hashcode()和equals()去除重复元素*///内部迭代:迭代操作由Stream API完成@Testpublic void test1() {// 中间操作:不会执行任何操作Stream<Employee> stream = employees.stream().filter((e) -> e.getAge() > 35);//终止操作:一次性抓行全部内容,即“惰性求值”stream.forEach(System.out::println);}/*** 外部迭代*/@Testpublic void test2() {Iterator<Employee> iterator = employees.iterator();while (iterator.hasNext()) {System.out.println(iterator.next());}}/*** limit 截断流*/@Testpublic void test3() {employees.stream().filter((e) -> {System.out.println("短路");return e.getSalary() > 5000;}).limit(2).forEach(System.out::println);}/*** skip 跳过*/@Testpublic void test4() {employees.stream().filter((e) -> e.getSalary() > 5000).limit(2).skip(2).forEach(System.out::println);}/*** distinct 去重*/@Testpublic void test5() {employees.stream().filter((e) -> e.getSalary() > 5000).limit(2).distinct().forEach(System.out::println);}/*** 映射* map—接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。* flatMap—接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流*/@Testpublic void test6() {List<String> list = Arrays.asList("aaa", "ccc", "ddd");list.stream().map((str) -> str.toUpperCase()).forEach(System.out::println);System.out.println("--------------------------------");Stream<Stream<Character>> stream = list.stream().map(TestStreamAPI2::filterCharacter);stream.forEach((sm) -> {sm.forEach(System.out::println);});System.out.println("--------------------------------");list.stream().flatMap(TestStreamAPI2::filterCharacter).forEach(System.out::println);}public static Stream<Character> filterCharacter(String str) {List<Character> list = new ArrayList<>();for (Character ch : str.toCharArray()) {list.add(ch);}return list.stream();}/*** sorted()—自然排序(Comparable)* sorted(Comparator com)—定制排序(Comparator)*/@Testpublic void test7() {List<String> list = Arrays.asList("aaa", "ccc", "ddd");list.stream().sorted().forEach(System.out::println);System.out.println("--------------------------------");employees.stream().sorted((e1, e2) -> {if (e1.getAge().equals(e2.getAge())) {return e1.getName().compareTo(e2.getName());} else {return e1.getAge().compareTo(e2.getAge());}}).forEach(System.out::println);}
}

终止操作(终端操作)

一个终止操作,执行中间操作链,并产生结果
在这里插入图片描述

package com.company;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee implements Serializable {private static final long serialVersionUID = 1L;private String name;private Integer age;private Double salary;private Status status;public enum Status{FREE,BUSY,VOCATION;}
}
package com.company;import org.junit.Test;import java.util.Arrays;
import java.util.List;
import java.util.Optional;/*** @author Helen* @version 1.0* @createTime 2023/2/9 23:58* @Description 终止操作*/
public class TestStreamAPI3 {/*** 查找与匹配* allMatch—检查是否匹配所有元素* anyMatch一检查是否至少匹配一个元素* noneMatch—检查是否没有匹配所有元素* findFirst—返回第一个元素* findAny—返回当前流中的任意元素* count—返回流中元素的总个数* max—返回流中最大值* min—返回流中最小值*/List<Employee> employees = Arrays.asList(new Employee("张三", 18, 9999.99, Employee.Status.FREE),new Employee("李四", 58, 5555.55, Employee.Status.BUSY),new Employee("王五", 26, 3333.33, Employee.Status.VOCATION),new Employee("赵六", 36, 6666.66, Employee.Status.FREE),new Employee("田七", 12, 8888.88, Employee.Status.BUSY));@Testpublic void test1() {boolean flag = employees.stream().allMatch(e -> e.getStatus().equals(Employee.Status.BUSY));System.out.println("flag=" + flag);boolean flag1 = employees.stream().anyMatch(e -> e.getStatus().equals(Employee.Status.BUSY));System.out.println("flag1=" + flag1);boolean flag2 = employees.stream().noneMatch(e -> e.getStatus().equals(Employee.Status.BUSY));System.out.println("flag2=" + flag2);// 按工资排序取出最大的值Optional<Employee> optional = employees.stream().sorted((e1, e2) -> -Double.compare(e1.getSalary(), e2.getSalary())).findFirst();System.out.println(optional.get());System.out.println("并行流,多个线程同时去查找");Optional<Employee> op2 = employees.parallelStream().filter((e) -> e.getStatus().equals(Employee.Status.FREE)).findAny();System.out.println(op2.get());}@Testpublic void test2() {Long count = employees.stream().count();System.out.println("count=" + count);Optional<Employee> optional = employees.stream().max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));System.out.println("获得最大值");System.out.println(optional.get());System.out.println("最小值");Optional<Double> op2 = employees.stream().map(Employee::getSalary).min(Double::compare);System.out.println(op2.get());}
}

归约与收集

在这里插入图片描述

package com.company;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** @author Helen* @version 1.0* @createTime 2023/2/5 16:32* @Description*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee implements Serializable {private static final long serialVersionUID = 1L;private String name;private Integer age;private Double salary;private Status status;public enum Status{FREE,BUSY,VOCATION;}
}
package com.company;import org.junit.Test;import java.util.*;
import java.util.stream.Collectors;/*** @author Helen* @version 1.0* @createTime 2023/2/15* @Description*/
public class TestStreamAPI4 {List<Employee> employees = Arrays.asList(new Employee("张三", 18, 9999.99, Employee.Status.FREE),new Employee("李四", 58, 5555.55, Employee.Status.BUSY),new Employee("王五", 26, 3333.33, Employee.Status.VOCATION),new Employee("赵六", 36, 6666.66, Employee.Status.FREE),new Employee("田七", 12, 8888.88, Employee.Status.BUSY),new Employee("田七", 12, 8888.88, Employee.Status.BUSY));/*** 归约* reduce(T identity,BinaryOperator)/ reduce(BinaryOperator)—可以将流中元素反复结合起来,得到一个值。* T identity:初始值* BinaryOperator:二进制操作,用于累加,相减*/@Testpublic void test() {System.out.println("第一种方式");List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);Integer sum = list.stream().reduce(0, (x, y) -> x + y);System.out.println("sum=" + sum);System.out.println("第二种方式");Integer sum2 = list.stream().reduce(0, Integer::sum);System.out.println("sum2=" + sum2);}/*** 收集* collect—将流转换为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法*/@Testpublic void test2() {System.out.println("--------------list类型收集--------------");List<String> list = employees.stream().map(Employee::getName).collect(Collectors.toList());list.forEach(System.out::println);System.out.println("--------------set类型收集--------------");Set<String> set = employees.stream().map(Employee::getName).collect(Collectors.toSet());set.forEach(System.out::println);System.out.println("----------------HashSet类型收集-------------");HashSet<String> hs = employees.stream().map(Employee::getName).collect(Collectors.toCollection(HashSet::new));hs.forEach(System.out::println);}@Testpublic void test3() {System.out.println("总数");Long count = employees.stream().collect(Collectors.counting());System.out.println(count);System.out.println("平均值");Double avg = employees.stream().collect(Collectors.averagingDouble(Employee::getSalary));System.out.println(avg);System.out.println("总和");Double sum = employees.stream().collect(Collectors.summingDouble(Employee::getSalary));System.out.println(sum);System.out.println("最大值");Optional<Employee> max = employees.stream().collect(Collectors.maxBy((e1, e2) ->Integer.compare(e1.getAge(), e2.getAge())));System.out.println(max.get());System.out.println("最小值");Optional<Double> min = employees.stream().map(Employee::getSalary).collect(Collectors.minBy(Double::compareTo));System.out.println(min.get());}/*** 分组*/@Testpublic void test4() {Map<Employee.Status, List<Employee>> map =employees.stream().collect(Collectors.groupingBy(Employee::getStatus));// jdk8遍历mapmap.forEach((k, v) -> {System.out.println(k);System.out.println(v);System.out.println("----------------");});/** 返回格式如下* BUSY* [Employee(name=李四, age=58, salary=5555.55, status=BUSY), Employee(name=田七, age=12, salary=8888.88, status=BUSY),* Employee(name=田七, age=12, salary=8888.88, status=BUSY)]*/}
}

并行流与顺序流

在这里插入图片描述

Fork/Join框架

在这里插入图片描述
在这里插入图片描述

package com.company;import java.util.concurrent.RecursiveTask;/*** @author Helen* @version 1.0* @createTime 2023/2/18* @Description*/
public class ForkJoinCalculate extends RecursiveTask<Long> {private static final long serialVersionUID = 1L;/*** 开始*/private long start;/*** 结束*/private long end;/*** 临界值*/private static final long THRESHOLD = 10000;public ForkJoinCalculate(long start, long end) {this.start = start;this.end = end;}@Overrideprotected Long compute() {long length = end - start;if (length <= THRESHOLD) {long sum = 0;for (long i = start; i <= end; i++) {sum += i;}return sum;} else {long middle = (start + end) / 2;ForkJoinCalculate left = new ForkJoinCalculate(start, middle);// 拆分子任务,同时加入线程队列left.fork();ForkJoinCalculate right = new ForkJoinCalculate(middle + 1, end);right.fork();return left.join() + right.join();}}
}
package com.company;import org.junit.Test;import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;/*** @author Helen* @version 1.0* @createTime 2023/2/18* @Description*/
public class TestForkJoin {/*** ForkJoin框架*/@Testpublic void test1() {Instant start = Instant.now();ForkJoinPool pool = new ForkJoinPool();ForkJoinTask<Long> task = new ForkJoinCalculate(0, 100000000000L);Long sum = pool.invoke(task);System.out.println(sum);Instant end = Instant.now();// 932356074711512064//耗费时间:12513毫秒System.out.println("耗费时间:" + Duration.between(start, end).toMillis() + "毫秒");}/*** 普通for循环*/@Testpublic void test2() {Instant start = Instant.now();long sum = 0L;for (long i = 0; i <= 100000000000L; i++) {sum += i;}System.out.println(sum);Instant end = Instant.now();//932356074711512064//耗费时间:26157毫秒System.out.println("耗费时间:" + Duration.between(start, end).toMillis() + "毫秒");}/*** java8并行流*/@Testpublic void test3() {Instant start = Instant.now();LongStream.rangeClosed(0, 100000000000L)// 并行流.parallel().reduce(0, Long::sum);Instant end = Instant.now();// 耗费时间:6971毫秒System.out.println("耗费时间:" + Duration.between(start, end).toMillis() + "毫秒");}
}

Optional类

在这里插入图片描述

package com.company;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** @author Helen* @version 1.0* @createTime 2023/2/5 16:32* @Description*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee implements Serializable {private static final long serialVersionUID = 1L;private String name;private Integer age;private Double salary;private Status status;public enum Status{FREE,BUSY,VOCATION;}
}
package com.company;import org.junit.Test;import java.util.Optional;/*** @author Helen* @version 1.0* @createTime 2023/2/18* @Description*/
public class OptionalTest {/*** 创建一个Optional实例*/@Testpublic void test1() {Optional<Employee> op = Optional.of(new Employee());Employee employee = op.get();System.out.println(employee);}@Testpublic void test2() {Optional<Employee> op = Optional.empty();System.out.println(op.get());}@Testpublic void test3() {Optional<Employee> op = Optional.ofNullable(null);if (op.isPresent()) {System.out.println("判断是否包含值");System.out.println(op.get());}Employee employee = op.orElse(new Employee("张三", 19, 888.88, Employee.Status.BUSY));System.out.println(employee);}@Testpublic void test4() {Optional<Employee> op = Optional.ofNullable(null);Employee employee = op.orElseGet(() -> new Employee());System.out.println(employee);}@Testpublic void test5() {Optional<Employee> op = Optional.ofNullable(new Employee("张三", 19, 888.88, Employee.Status.BUSY));Optional<String> str = op.map(Employee::getName);System.out.println(str.get());}@Testpublic void test6() {Optional<Employee> op = Optional.ofNullable(new Employee("张三", 19, 888.88, Employee.Status.BUSY));Optional<String> str = op.flatMap((e) -> Optional.of(e.getName()));System.out.println(str.get());}
}

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

在这里插入图片描述

package com.company;public class MyClass {public String getName() {return "嘿嘿";}
}
package com.company;public interface MyFun {/*** 接口中的默认方法,用default修饰** @return*/default String geName() {return "哈哈";}/*** 接口中的静态方法的调用* 类名.静态方法名()*/public static void say(){System.out.println("接口中的静态方法");}
}
package com.company;
public class SubClass extends MyClass implements MyFun{
}
package com.company;public class DefaultInterfaceTest {public static void main(String[] args) {SubClass sc = new SubClass();String str = sc.geName();System.out.println(str);}
}

输出 哈哈

时间和日期

传统时间格式化

package com.company;import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;/*** @author Helen* @version 1.0* @createTime 2023/2/18* @Description 传统时间格式化线程问题*/
public class SimpleDateFormatTest {public static void main(String[] args) throws Exception {SimpleDateFormat sf = new SimpleDateFormat("yyyyMMdd");Callable<Date> task = new Callable<Date>() {@Overridepublic Date call() throws Exception {return sf.parse("20230218");}};// 固定数量的线程池ExecutorService pool = Executors.newFixedThreadPool(10);List<Future<Date>> results = new ArrayList<>();for (int i = 0; i < 10; i++) {results.add(pool.submit(task));}for (Future<Date> future : results) {System.out.println(future.get());}}
}

上述代码,出现日期格式解析失败,修复代码如下

package com.company;import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;/*** @author Helen* @version 1.0* @createTime 2023/2/18* @Description*/
public class DateFormatThreadLocal {private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {@Overrideprotected DateFormat initialValue() {return new SimpleDateFormat("yyyyMMdd");}};public static Date convert(String source) throws Exception {return df.get().parse(source);}
}
package com.company;import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;/*** @author Helen* @version 1.0* @createTime 2023/2/18* @Description 传统时间格式化线程问题*/
public class SimpleDateFormatTest {public static void main(String[] args) throws Exception {SimpleDateFormat sf = new SimpleDateFormat("yyyyMMdd");Callable<Date> task = new Callable<Date>() {@Overridepublic Date call() throws Exception {return DateFormatThreadLocal.convert("20230218");}};// 固定数量的线程池ExecutorService pool = Executors.newFixedThreadPool(10);List<Future<Date>> results = new ArrayList<>();for (int i = 0; i < 10; i++) {results.add(pool.submit(task));}for (Future<Date> future : results) {System.out.println(future.get());}// 关闭线程pool.shutdown();}
}

jdk8中的日期

在这里插入图片描述

package com.company;import org.junit.Test;import java.time.*;/*** @author Helen* @version 1.0* @createTime 2023/2/18* @Description*/
public class DateDemo {/*** 系统当前时间*/@Testpublic void test1() {LocalDateTime ldt = LocalDateTime.now();System.out.println(ldt);LocalDateTime ldt2 = LocalDateTime.of(2023, 2, 18, 22, 10);System.out.println(ldt2);LocalDateTime ldt3 = ldt.plusYears(2);System.out.println(ldt3);LocalDateTime ldt4 = ldt.minusMonths(2);System.out.println(ldt4);}/*** Instant:时间戳(以Unix元年:1970年1月1日 00:00:00)*/@Testpublic void test2() {//默认获取UTC时区Instant now = Instant.now();System.out.println(now);// 偏移量OffsetDateTime of = now.atOffset(ZoneOffset.ofHours(8));System.out.println(of);// 毫秒时间System.out.println(now.toEpochMilli());// 秒Instant instant = Instant.ofEpochSecond(1000);System.out.println("instant=" + instant);}/*** Duration:计算两个“时间”之间的间隔*/@Testpublic void test3() {Instant ins1 = Instant.now();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}Instant ins2 = Instant.now();Duration duration = Duration.between(ins1, ins2);// 获取时间以秒为单位System.out.println("秒=" + duration.getSeconds());// 获取毫秒System.out.println("毫秒=" + duration.toMillis());}/*** Period:计算两个“日期”之间的间隔*/@Testpublic void test4() {LocalDate ld1 = LocalDate.of(2022, 1, 5);LocalDate ld2 = LocalDate.now();Period period = Period.between(ld1, ld2);System.out.println("相差年数:" + period.getYears());System.out.println("相差月数:" + period.getMonths());System.out.println("相差天数:" + period.getDays());}
}

时间校正器

在这里插入图片描述

package com.company;import org.junit.Test;import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;/*** @author Helen* @version 1.0* @createTime 2023/2/19* @Description*/
public class DateDemo2 {/*** 时间校正器 TemporalAdjuster*/@Testpublic void test1() {LocalDateTime ldt1 = LocalDateTime.now();System.out.println("ldt1=" + ldt1);LocalDateTime ldt2 = ldt1.withDayOfMonth(10);System.out.println("ldt2=" + ldt2);}@Testpublic void test2() {LocalDate nextSunday = LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.SUNDAY));System.out.println("下个周日:" + nextSunday);// 下一个工作日LocalDateTime ldt1 = LocalDateTime.now();LocalDateTime day = ldt1.with((l) -> {LocalDateTime ldt2 = (LocalDateTime) l;DayOfWeek dow = ldt2.getDayOfWeek();if (dow.equals(DayOfWeek.MONDAY)) {ldt2.plusDays(1);} else if (dow.equals(DayOfWeek.TUESDAY)) {ldt2.plusDays(2);} else if (dow.equals(DayOfWeek.WEDNESDAY)) {ldt2.plusDays(3);} else if (dow.equals(DayOfWeek.THURSDAY)) {ldt2.plusDays(4);} else if (dow.equals(DayOfWeek.FRIDAY)) {ldt2.plusDays(5);} else if (dow.equals(DayOfWeek.SATURDAY)) {ldt2.plusDays(8);} else if (dow.equals(DayOfWeek.SUNDAY)) {ldt2.plusDays(9);}return ldt2;});System.out.println("下一个工作日=" + day);}/*** DateTimeFormatter:格式化时间/日期*/@Testpublic void test3() {DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME;LocalDateTime ldt = LocalDateTime.now();String str = ldt.format(dtf);System.out.println(str);System.out.println("----------------------------");DateTimeFormatter df2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");String strDate2 = df2.format(ldt);LocalDateTime newDate = LocalDateTime.parse(strDate2, df2);System.out.println(newDate);}
}

时区的处理

在这里插入图片描述

package com.company;import org.junit.Test;import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;public class DateDemo2 {/*** ZoneDate、ZonedTime、ZonedDateTime*/@Testpublic void test4() {LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Europe/Tallinn"));// 2023-02-19T17:53:10.695System.out.println(ldt);System.out.println("---------------------");LocalDateTime ldt2 = LocalDateTime.now();ZonedDateTime zdt = ldt.atZone(ZoneId.of("Europe/Tallinn"));// 2023-02-19T17:53:10.695+02:00[Europe/Tallinn]System.out.println(zdt);}
}

重复注解与类型注解

在这里插入图片描述

package com.company;import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;import static java.lang.annotation.ElementType.*;/*** @author Helen* @version 1.0* @createTime 2023/2/20* @Description @Repeatable:可重复的注解* MyAnnotations.class:容器类*/@Repeatable(MyAnnotations.class)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE,TYPE_PARAMETER})
@Retention(RetentionPolicy.SOURCE)
public @interface MyAnnottation {String value() default "atguigu";}
package com.company;import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;/*** @author Helen* @version 1.0* @createTime 2023/2/20* @Description*/
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotations {MyAnnottation[] value();
}
package com.company;import org.junit.Test;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;/*** @author Helen* @version 1.0* @createTime 2023/2/20* @Description*/
public class TestAnnotation {@Testpublic void test() throws Exception {Class<TestAnnotation> clazz = TestAnnotation.class;Method method = clazz.getMethod("show");MyAnnottation[] mas = method.getAnnotationsByType(MyAnnottation.class);for (MyAnnottation m : mas) {System.out.println(m.value());}}@MyAnnottation("Hello")@MyAnnottation("World")public void show() {}
}

输出
Hello
World

相关文章:

Java8新特性学习

Java8新特性学习为啥使用Lambda表达式Lambda表达式的基础语法无参无返回有参无返回一个参数多参单个语句体类型推断四大内置核心函数式接口其他接口方法引用与构造器引用Stream简介什么是StreamStream操作步骤创建Stream中间操作终止操作(终端操作&#xff09;归约与收集并行流…...

SPARK outputDeterministicLevel的作用--任务全部重试或者部分重试

背景 目前spark的repartition()方法是随机分配数据到下游&#xff0c;这会导致一个问题&#xff0c;有时候如果我们用repartition方法的时候&#xff0c;如果任务发生了重试&#xff0c;就有可能导致任务的数据不准确&#xff0c;那这个时候改怎么解决这个问题呢&#xff1f; …...

图数据库中的 OLTP 与 OLAP 融合实践

在一些图计算的场景下&#xff0c;我们会遇到同时需要处理 OLTP 和 OLAP 的问题。而本文就给了一个 OLTP 与 OLAP 融合实践的指导思路&#xff0c;希望给你带来一点启发。 Dag Controller 介绍 Dag Controller 是 NebulaGraph 企业版的图系统&#xff0c;经过反复测试无误后已…...

Shader Graph简介

使用着色器&#xff08;shader&#xff09;和材质&#xff08;material&#xff09;&#xff0c;我们能够创造出非常多有趣的效果。除了Unity自带的shader外&#xff0c;还可以自己编写shader或使用其他人所编写的shader。编写shader通常需要我们了解shader编程语言的语法和相关…...

kubectl

目录 一、陈述式资源管理方法 二、基本信息查看 2.1 基本信息查看格式 2.2 查看master节点组件状态 2.3 查看命名空间 2.4 创建/查看命名空间 2.5 删除&#xff08;重启&#xff09;命名空间/pod 2.6 查看资源的详细信息 2.7 创建副本控制器来启动Pod 2.8 查看指定命…...

实验室设计SICOLAB第三方检测中心实验室设计

第三方检测中心实验室怎么设计&#xff1f;详细设计内容有哪些&#xff1f;功能区域有哪些&#xff1f;仪器有哪些&#xff1f;要多少面积&#xff1f;第三方检测中心实验室是一种独立的实验室&#xff0c;为客户提供各种测试和分析服务。以下是一个第三方检测中心实验室的详细…...

GPS经纬度转距离

function [pN, pE] distance_gps(lon1, lon2, lat1, lat2)d2r pi/180; % deg转radR 6371000.0; % 地球半径pN (lat2 - lat1) * d2r * R;pE (lon2 - lon1) * d2r * R * cos(lat2 * d2r); end...

7-周赛333总结

7-周赛333总结 还是只过了前两题&#xff0c;第三题又写了好久好久&#xff0c;然后也不知道错在了哪里&#xff0c;只过了部分题解&#xff0c;也许是思考不全面吧。下次也许先做第四题更好…第四题今天花了点时间 做出来了个大概 开心 :happy: 合并两个二维数组 - 求和法【…...

电子招标采购系统源码—互联网+招标采购

智慧寻源 多策略、多场景寻源&#xff0c;多种看板让寻源过程全程可监控&#xff0c;根据不同采购场景&#xff0c;采取不同寻源策略&#xff0c; 实现采购寻源线上化管控&#xff1b;同时支持公域和私域寻源。 询价比价 全程线上询比价&#xff0c;信息公开透明&#xff0c;可…...

SQL注入和XSS攻击

1、SQL注入 所谓SQL注入&#xff0c;就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串&#xff0c;最终达到欺骗服务器执行恶意的SQL命令。 我们永远不要信任用户的输入&#xff0c;我们必须认定用户输入的数据都是不安全的&#xff0c;我们都需要对用户输…...

js Map的使用

前言&#xff1a;Map数据集可以理解为加强版的对象 一、for...of 1、对象不能用于for of&#xff0c;因其没有部署Iterator接口&#xff1b;其他数据集如&#xff1a;数组、Map、Set、Iterator对象等都可以用for...of2、使用for...of的优势&#xff1a; for of的循环体中可以…...

企业应该怎么管理香港服务器?

做好服务器管理&#xff0c;往往能为站长避免很多麻烦。用户租用服务器&#xff0c;除了希望它快速而安全&#xff0c;还有就是如何才能得到优质及时的售后和指导建议了。服务器供应商只提供服务器管理的基础服务&#xff0c;负责提供硬件、带宽和电力等服务&#xff0c;服务器…...

软件设计(十四)-UML建模(上)

软件设计&#xff08;十三&#xff09;-原码、反码、补码、移码https://blog.csdn.net/ke1ying/article/details/129115844?spm1001.2014.3001.5501 UML建模包含&#xff1a;用例图&#xff0c;类图与对象图&#xff0c;顺序图&#xff0c;活动图&#xff0c;状态图&#xff…...

本地主机搭建服务器后如何让外网访问?快解析内网端口映射

本地主机搭建应用、部署服务器后&#xff0c;在局域网内是可以直接通过计算机内网IP网络地址进行连接访问的&#xff0c;但在外网电脑和设备如何访问呢&#xff1f;由于内网环境下&#xff0c;无法提供公网IP使用&#xff0c;外网访问内网就需要一个内外网转换的介质。这里介绍…...

Flink-Table API 和 SQL(基本API、流处理的表、时间属性和窗口、聚合查询、联结查询、函数、SQL客户端、连接到外部系统)

文章目录Table API 和 SQL快速上手基本 API程序架构创建表环境创建表表的查询输出表表和流的转换流处理中的表动态表和持续查询将流转换成动态表原理用 SQL 持续查询-更新查询&追加查询将动态表转换为流(Append-only、Retract、Upsert)时间属性和窗口事件时间处理时间窗口&…...

C++入门:数据抽象

数据抽象是指&#xff0c;只向外界提供关键信息&#xff0c;并隐藏其后台的实现细节&#xff0c;即只表现必要的信息而不呈现细节。数据抽象是一种依赖于接口和实现分离的编程&#xff08;设计&#xff09;技术。让我们举一个现实生活中的真实例子&#xff0c;比如一台电视机&a…...

WRF进阶:使用IO选项控制WRF变量输出/WRF指定变量输出添加/删除

Registry文件 WRF模式在运行求解时&#xff0c;会涉及到大量的数据变量运算&#xff0c;而这些数据变量的管理、规定、控制则需要依赖于WRF的Registry文件&#xff0c;简单来说&#xff0c;它可以理解为管理WRF数据结构的“数据字典”&#xff08;"Active data-dictionar…...

一文读懂功率放大器(功率放大器的特性是什么意思)

功率放大器是一种电子放大器&#xff0c;旨在增加给定输入信号的功率幅度。功率放大器一般要求得到一定的不失真或者较小失真的输出功率&#xff0c;在大信号状态下进行工作&#xff0c;主要是输出较大功率。功率放大器的特性介绍&#xff1a;1、增益功率放大器的增益主要是指放…...

微信小程序阻止页面返回(包滑动、自动返回键)

这个场景还是挺有意思的&#xff0c;比如某多多&#xff0c;只要你点左上角的返回 好家伙&#xff0c;满满又 花不了 的优惠券就来了&#xff0c;让你拥有一种消费最划算的感觉。 如果你的场景比较简单&#xff0c;只是对左上角的返回进行监听&#xff0c;只需要关闭自带的导航…...

视频直播美颜sdk的发展史

视频直播美颜sdk的出现是必然的&#xff0c;它的诞生就是为了让更多用户能够更好地体验到视频直播带给大家的快乐&#xff0c;可以说视频直播美颜sdk的发展和用户体验有着紧密联系。今天&#xff0c;小编不聊技术&#xff0c;咱们来聊一下视频直播美颜sdk的诞生以及发展历程。 …...

NoSQL 之 Redis 配置与优化

目录 一、 前置知识点 1. 关系数据库与非关系型数据库 &#xff08;1&#xff09;关系型数据库 &#xff08;2&#xff09;非关系型数据库 &#xff08;3&#xff09;非关系型数据库产生背景 &#xff08;4&#xff09;两者对比 2. Redis 基础 &#xff08;1&#xff0…...

WaytoAGI东京大会开启AI全球化新对话:技术无国界,合作促创新

全球AI专家齐聚东京&#xff0c;一场关于技术无国界的对话正在进行。 2025年6月7日&#xff0c;一场备受瞩目的AI盛会——“WaytoAGI全球AI大会东京站”在日本东京樱美林大学新宿校区正式拉开帷幕。这场为期两天的会议&#xff08;6月7日至8日&#xff09;由国内最大的AI开源知…...

每日Prompt:云朵猫

提示词 仰视&#xff0c;城镇的天空&#xff0c;一片形似猫咪的云朵&#xff0c;用黑色的简笔画&#xff0c;勾勒出猫咪的形状&#xff0c;可爱&#xff0c;俏皮&#xff0c;极简...

# STM32F103 SD卡读写程序

下面是一个基于STM32F103系列微控制器的SD卡读写完整程序&#xff0c;使用标准外设库(StdPeriph)和FatFs文件系统。 硬件准备 STM32F103C8T6开发板(或其他F103系列)SD卡模块(SPI接口)连接线缆 硬件连接 SD卡模块 STM32F103 CS -> PA4 (SPI1_NSS) SCK -> PA5 (SPI…...

buuctf——web刷题第二页

[网鼎杯 2018]Fakebook和[SWPU2019]Web1没有&#xff0c;共30题 目录 [BSidesCF 2020]Had a bad day [网鼎杯 2020 朱雀组]phpweb [BJDCTF2020]The mystery of ip [BUUCTF 2018]Online Tool [GXYCTF2019]禁止套娃 [GWCTF 2019]我有一个数据库 [CISCN2019 华北赛区 Day2…...

React项目的状态管理:Redux Toolkit

目录 1、搭建环境 2、Redux Toolkit 包含了什么 3、使用示例 &#xff08;1&#xff09;创建user切片 &#xff08;2&#xff09;合并切片得到store &#xff08;3&#xff09;配置store和使用store 使用js来编写代码&#xff0c;方便理解一些 1、搭建环境 首先&#xf…...

小白如何在cursor中使用mcp服务——以使用notion的api为例

1. 首先安装node.js,在这一步的时候不要勾选不要勾选 2. 安装完之后,前往notion页面 我的创作者个人资料 | Notion 前往集成页面&#xff0c;添加新集成&#xff0c;自己输入名字&#xff0c;选择内部 新建完之后&#xff0c;进入选择只读 复制密匙 然后前往cursor页面 新建…...

PPT转图片拼贴工具 v1.0

软件介绍 这个软件的作用就是将单个PPT的每一页转换为单独的图片&#xff0c;然后将图片进行拼接起来。 但是我没有还没有解决一次性处理多个文件。 效果展示如下&#xff1a; 软件安装 软件源码 import os import re import win32com.client from PIL import Imagedef con…...

DVWA全靶场

目录 暴破 Low - 万能密码 Medium - 转义 High - Token Impossible 命令注入 CSRF跨站请求伪造 - 抓包 Low Medium - 域名限制 High - 域名限制xss 文件包含 - 页面点点点 Low Medium - 过滤http:// High - file Impossible - 写死 文件上传 Low Medium - 文件…...

如何自定义一个 Spring Boot Starter?

导语&#xff1a; 在后端 Java 面试中&#xff0c;Spring Boot 是绕不开的重点&#xff0c;而“如何自定义一个 Starter”作为进阶开发能力的体现&#xff0c;常被面试官用于考察候选人的工程架构思维与 Spring Boot 底层掌握程度。本文将带你深入理解自定义 Starter 的实现逻辑…...