8.Java各版本特性
1.Java8
- 1.
Lambda
表达式 - 2.函数式接口
- 3.方法引用
- 4.默认方法
- 5.
Stream API
- 6.
Optional
类 - 7.
Date Time API
- 8.
Nashorn、JavaScript
引擎
1.Lambda表达式
- 1.
定义
:Lambda
表达式是对匿名函数
的简写形式
,Lambda
允许把函数作为一个方法的参数,可以写出更简洁的代码 - 2.
实质
:语法糖
,实质底层还是一个方法
package domains;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class Employee {
private String name;
private int age;
private double salary;
}
package dao;
public interface TestPredicate<T> {
boolean test(T e);
}
package dao.daoImpl;
import dao.TestPredicate;
import domains.Employee;
public class FilterEmployeeByAge implements TestPredicate<Employee> {
@Override
public boolean test(Employee employee) {
return employee.getAge() > 24;
}
}
package dao.daoImpl;
import dao.TestPredicate;
import domains.Employee;
public class FilterEmployeeBySalary implements TestPredicate<Employee> {
@Override
public boolean test(Employee employee) {
return employee.getSalary() > 8000;
}
}
import dao.TestPredicate;
import dao.daoImpl.FilterEmployeeByAge;
import dao.daoImpl.FilterEmployeeBySalary;
import domains.Employee;
import org.junit.Test;
import java.util.*;
public class TestLambda {
List<Employee> employees = Arrays.asList(
new Employee("张三",8,100),
new Employee("李四",12,500),
new Employee("王五",18,3000),
new Employee("赵六",24,8000),
new Employee("田七",35,15000),
new Employee("吴八",40,25000)
);
@Test
public void test1(){
Comparator<Integer> comparator = new Comparator<Integer>(){
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1,o2);
}
};
TreeSet<Integer> treeSet = new TreeSet<>(comparator);
}
@Test
public void test2(){
Comparator<Integer> comparator = (x,y) -> Integer.compare(x,y);
TreeSet<Integer> treeSet = new TreeSet<>(comparator);
TreeSet<Integer> integerTreeSet = new TreeSet<>((x,y) -> Integer.compare(x,y));
}
@Test
public void test3(){
List<Employee> filterEmployees = filterAgeEmployees(employees);
for (Employee filterEmployee : filterEmployees) {
System.out.println(filterEmployee);
}
}
@Test
public void test4(){
List<Employee> filterEmployees = filterEmployee(employees, new FilterEmployeeByAge());
for (Employee filterEmployee : filterEmployees) {
System.out.println(filterEmployee);
}
}
@Test
public void test5(){
List<Employee> filterEmployees = filterSalaryEmployees(employees);
for (Employee filterEmployee : filterEmployees) {
System.out.println(filterEmployee);
}
}
@Test
public void test6(){
List<Employee> filterEmployees = filterEmployee(employees,new FilterEmployeeBySalary());
for (Employee filterEmployee : filterEmployees) {
System.out.println(filterEmployee);
}
}
public List<Employee> filterAgeEmployees(List<Employee> employees){
ArrayList<Employee> employeeArrayList = new ArrayList<>();
for (Employee employee : employees) {
if(employee.getAge() > 24){
employeeArrayList.add(employee);
}
}
return employeeArrayList;
}
public List<Employee> filterSalaryEmployees(List<Employee> employees){
ArrayList<Employee> employeeArrayList = new ArrayList<>();
for (Employee employee : employees) {
if(employee.getSalary() > 8000){
employeeArrayList.add(employee);
}
}
return employeeArrayList;
}
public List<Employee> filterEmployee(List<Employee> list, TestPredicate<Employee> predicate){
ArrayList<Employee> employeeArrayList = new ArrayList<>();
for (Employee employee : employees) {
if(predicate.test(employee)){
employeeArrayList.add(employee);
}
}
return employeeArrayList;
}
@Test
public void test7(){
List<Employee> filterEmployees = filterEmployee(employees,new TestPredicate<Employee>(){
@Override
public boolean test(Employee employee) {
return employee.getSalary() < 5000;
}
});
for (Employee filterEmployee : filterEmployees) {
System.out.println(filterEmployee);
}
}
@Test
public void test8(){
List<Employee> filterEmployees = filterEmployee(employees,(e) -> e.getSalary() < 5000);
filterEmployees.forEach(System.out::println);
}
@Test
public void test9(){
employees.stream().filter((e) -> e.getSalary() < 5000).forEach(System.out::println);
}
}
1.Lambda基础语法
import org.junit.Test;
import java.util.Comparator;
import java.util.function.Consumer;
public class TestLambda2 {
@Test
public void test1(){
Runnable runnable = new Runnable(){
@Override
public void run() {
System.out.println("Hello World");
}
};
runnable.run();
Runnable lambda = () -> System.out.println("Hello Lambda");
lambda.run();
}
@Test
public void test2(){
Consumer<String> consumer = x -> System.out.println(x);
consumer.accept("测试成功!");
}
@Test
public void test3(){
Comparator<Integer> comparator = (x, y) -> {
System.out.println("测试成功!");
return Integer.compare(x, y);
};
}
@Test
public void test4(){
Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);
}
}
2.Lambda上下文推断
String[] strs = {"aaa","bbb","ccc"}
List<String> list = new ArrayList<>();
show(new HashMap<>());
public void show(Map<String, Integer> map){
...
}
2.函数式接口
- 1.定义: 只包含一个
抽象方法
的接口 - 2.使用
@FunctionalInterface
注解,可以检查是否为函数式接口
1.四大核心函数式接口
函数式接口 | 参数类型 | 返回类型 | 用途 |
---|
Consumer<T> 消费型接口 | T | void | 对类型为T的对象应用操作。包含方法:void accept(T t) |
Supplier<T> 供给型接口 | 无 | T | 返回类型为T的对象。包含方法:T get() |
Function<T, R> 函数型接口 | T | R | 对类型为T的对象应用操作,并返回R类型对象的结果。包含方法:R apply(T t) |
Predicate<T> 断言型接口 | T | boolean | 确定类型为T的对象是否满足某约束。包含方法:boolean test(T t) |
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;
public class TestLambda4 {
@Test
public void test1(){
shopping(1000,(m) -> System.out.println("书包,消费" + m/4));
}
public void shopping(double money, Consumer<Double> consumer){
consumer.accept(money);
}
@Test
public void test2(){
List<Integer> integers = getIntegers(10, () -> (int) (Math.random() * 100));
for (Integer integer : integers) {
System.out.println(integer);
}
}
public List<Integer> getIntegers(int num, Supplier<Integer> supplier){
List<Integer> list = new ArrayList<>();
for (int i = 0; i < num; i++) {
Integer n = supplier.get();
list.add(n);
}
return list;
}
@Test
public void test3(){
String s = strHandler("三生三世:十里桃花", (str) -> str.replace(":", "+"));
System.out.println(s);
}
public String strHandler(String str, Function<String,String> function){
return function.apply(str);
}
@Test
public void test4(){
List<String> statement = Arrays.asList("三生三世,十里桃花","人生若只如初见","三生三世,情非得已");
List<String> stringList = filterStr(statement, (str) -> str.contains("三生三世"));
for (String s : stringList) {
System.out.println(s);
}
}
public List<String> filterStr(List<String> list, Predicate<String> predicate){
List<String> stringList = new ArrayList<>();
for (String s : list) {
if(predicate.test(s)){
stringList.add(s);
}
}
return stringList;
}
}
2.其他函数式接口
函数式接口 | 参数类型 | 返回类型 | 用途 |
---|
BiConsumer<T,U> | T,U | void | 对类型为T,U的对象应用操作。包含方法:void accept(T t,U u) |
BiFunction<T,U,R> | T,U | R | 对类型为T,U参数的对象应用操作,返回R类型的结果。包含方法:R apply(T t,U u) |
BiPredicate<T,U> | T,U | boolean | 确定类型为T,U的对象是否满足某约束。包含方法:boolean test(T t, U u) |
3.引用
- 1.
Lambda
表达式的另一种写法 - 2.当要传递给
Lambda
体的操作已经有实现则可以使用方法引用
1.方法引用
import domains.Employee;
import org.junit.Test;
import java.util.Comparator;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
public class TestLambda5 {
@Test
public void test1(){
Consumer<String> consumer = (x) -> System.out.println(x);
Consumer<String> consumer1 = System.out::println;
consumer1.accept("200");
shopping(1000, System.out::println);
}
public void shopping(double money, Consumer<Double> consumer){
consumer.accept(money);
}
@Test
public void test2(){
Comparator<Integer> comparator = (x, y) -> Integer.compare(x,y);
Comparator<Integer> comparator1 = Integer::compareTo;
}
@Test
public void test3(){
BiPredicate<String, String> biPredicate = (x, y) -> x.equals(x);
BiPredicate<String, String> biPredicate1 = String::equals;
}
}
2.构造器引用
@Test
public void test4(){
Supplier<Employee> supplier = () -> new Employee();
supplier.get();
Supplier<Employee> supplier1 = Employee::new;
Employee employee = supplier1.get();
System.out.println(employee);
Function<Integer, Employee> function = Employee::new;
Employee apply = function.apply(1);
System.out.println(apply);
}
3.数组引用
@Test
public void test5(){
Function<Integer, String[]> function = (x) -> new String[x];
String[] apply = function.apply(10);
System.out.println(apply.length);
Function<Integer, String[]> function1 = String[]::new;
String[] apply1 = function1.apply(20);
System.out.println(apply1.length);
}
5.Stream
1.Stream的概念
- Stream是Java8处理集合的关键抽象概念,它可以指定对集合进行的操作,可以执行非常复杂的查找,过滤,映射数据等操作
- 流(Stream)是数据通道,用于操作数据源(集合,数组等)所生成的元素序列
- 完整流包含以下结构:
- 1.数据源(集合,数组等)
- 2.通道(做一系列流水线式的中间操作)
- 3.新流(终止操作产生)
- 注意:
- 1.Stream不会存储元素
- 2.Stream不会改变数据源,而是返回一个持有结果的新Stream
- 3.Stream操作是延迟执行的,即等到需要结果(终止操作)的时候才会被执行
2.Stream的操作三个步骤
- 1.创建Stream
- 2.中间操作
- Stream的一个中间操作链,对数据源的数据进行处理
- 3.终止操作
- Stream的一个终止操作,执行中间操作链,并产生结果
3.创建Stream的四种方式
import domains.Employee;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.stream.Stream;
public class TestLambda6 {
@Test
public void test1(){
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
Employee[] employees = new Employee[10];
Stream<Employee> stream1 = Arrays.stream(employees);
Stream<String> stream3 = Stream.of("aa", "bb", "cc");
Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);
Stream<Integer> limit = stream4.limit(10);
limit.forEach(System.out::println);
Stream.generate(() -> new Random().nextInt(100)).limit(10).forEach(System.out::println);
}
}
4.中间操作
- 延迟加载:中间操作默认不会执行任何操作,只有执行了终止操作,所有的中间操作才会执行,这个过程叫做惰性求值或者延迟加载(多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理,而在终止操作时一次性全部处理)
- 内部迭代:迭代操作由Stream API完成
- 外部迭代:手动完成
1.筛选与切片
List<Employee> employees = Arrays.asList(
new Employee("张三",8,100),
new Employee("李四",12,500),
new Employee("王五",18,3000),
new Employee("赵六",24,8000),
new Employee("赵九",24,6000),
new Employee("田七",35,15000),
new Employee("吴八",40,25000),
new Employee("吴八",40,25000)
);
@Test
public void test2(){
employees.stream().filter((e) -> e.getAge() > 24).forEach(System.out::println);
employees.stream().filter((e) -> e.getAge() > 24).limit(1).forEach(System.out::println);
employees.stream().filter((e) -> e.getAge() > 24).skip(1).forEach(System.out::println);
employees.stream().filter((e) -> e.getAge() > 24).distinct().forEach(System.out::println);
}
2.映射
@Test
public void test3(){
List<String> list = Arrays.asList("aaa","bbb","ccc");
list.stream()
.map((str) -> str.toUpperCase())
.forEach(System.out::println);
employees.stream().map(Employee::getName).forEach(System.out::println);
Stream<Stream<Character>> streamStream = list.stream().map(TestLambda6::filterCharacter);
streamStream.forEach((stream) -> {
stream.forEach(System.out::println);
});
Stream<Character> characterStream = list.stream().flatMap(TestLambda6::filterCharacter);
characterStream.forEach(System.out::println);
List<String> list1 = Arrays.asList("aaa", "bbb", "ccc");
List list2 = new ArrayList<>();
list2.add("111");
list2.add("222");
list2.add("333");
list2.add(list1);
list2.addAll(list1);
System.out.println(list2);
}
public static Stream<Character> filterCharacter(String str){
List<Character> list = new ArrayList<>();
for (Character c : str.toCharArray()) {
list.add(c);
}
return list.stream();
}
3.排序
@Test
public void test4(){
List<String> list = Arrays.asList("ccc", "aaa", "bbb");
list.stream()
.sorted()
.forEach(System.out::println);
employees.stream().sorted((e1 ,e2) -> {
if(e1.getAge() == e2.getAge()){
return e1.getName().compareTo(e2.getName());
}else {
return -e1.getAge() - e2.getAge();
}
}).forEach(System.out::println);
}
5.终止操作
1.查找与匹配
@Test
public void test5(){
boolean b = employees.stream().allMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
System.out.println(b);
boolean b1 = employees.stream().anyMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
System.out.println(b1);
boolean b2 = employees.stream().noneMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
System.out.println(b2);
Optional<Employee> first = employees.stream().findFirst();
System.out.println(first.get());
Optional<Employee> any = employees.parallelStream().findAny();
System.out.println(any.get());
long count = employees.stream().count();
System.out.println(count);
Optional<Employee> max = employees.stream().max(Comparator.comparingDouble(Employee::getSalary));
System.out.println(max.get());
Optional<Double> min = employees.stream().map(Employee::getSalary).min(Double::compareTo);
System.out.println(min.get());
}
2.归约
@Test
public void test6(){
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);
}
3.收集
@Test
public void test7(){
List<Person> list = new ArrayList<>();
list.add(new Person("Ram", 30));
list.add(new Person("Shyam", 20));
list.add(new Person("Shiv", 20));
list.add(new Person("Mahesh", 30));
String nameByAge = list.stream().collect(Collectors.mapping(Person::getName, Collectors.joining(",", "[", "]")));
System.out.println(nameByAge);
nameByAge = list.stream().map(person -> person.getName()).collect(Collectors.joining(",", "[", "]"));
System.out.println(nameByAge);
Map<Integer, String> nameByAgeMap = list.stream().collect(
Collectors.groupingBy(Person::getAge, Collectors.mapping(Person::getName, Collectors.joining(",", "[", "]"))));
nameByAgeMap.forEach((k, v) -> System.out.println("Age:" + k + " Persons: " + v));
List<String> list1 = Arrays.asList("A","B","C","D");
String result= list1.stream().collect(Collectors.joining("-","[","]"));
System.out.println(result);
List<String> collect = employees.stream()
.map(Employee::getName)
.collect(Collectors.toList());
collect.forEach(System.out::println);
Set<String> collect1 = employees.stream()
.map(Employee::getName)
.collect(Collectors.toSet());
collect1.forEach(System.out::println);
Map<String, Double> collect8 = employees.stream().collect(Collectors.toMap(Employee::getName, Employee::getSalary, (e1, e2) -> e1));
for (Map.Entry<String, Double> stringDoubleEntry : collect8.entrySet()) {
System.out.println(stringDoubleEntry.getKey() + ":" + stringDoubleEntry.getValue());
}
ConcurrentMap<String, Double> collect9 = employees.stream().collect(Collectors.toConcurrentMap(Employee::getName, Employee::getSalary, (e1, e2) -> e1));
for (Map.Entry<String, Double> stringDoubleEntry : collect9.entrySet()) {
System.out.println(stringDoubleEntry.getKey() + ":" + stringDoubleEntry.getValue());
}
HashSet<String> collect2 = employees.stream()
.map(Employee::getName)
.collect(Collectors.toCollection(HashSet::new));
collect2.forEach(System.out::println);
Long collect3 = employees.stream()
.collect(Collectors.counting());
System.out.println(collect3);
Double collect4 = employees.stream()
.collect(Collectors.averagingDouble(Employee::getSalary));
System.out.println(collect4);
DoubleSummaryStatistics collect5 = employees.stream()
.collect(Collectors.summarizingDouble(Employee::getSalary));
System.out.println(collect5);
Optional<Employee> collect6 = employees.stream()
.collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
System.out.println(collect6.get());
Optional<Employee> collect7 = employees.stream()
.collect(Collectors.minBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
System.out.println(collect7.get());
}
4.分组
@Test
public void test8(){
Map<Employee.Status, List<Employee>> collect = employees.stream().collect(Collectors.groupingBy(Employee::getStatus));
for (Map.Entry<Employee.Status, List<Employee>> statusListEntry : collect.entrySet()) {
System.out.println(statusListEntry.getKey() + ":" + statusListEntry.getValue());
}
Map<Employee.Status, Map<String, List<Employee>>> collect1 = employees.stream().collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
if (e.getAge() <= 35) {
return "青年";
} else if (e.getAge() <= 50) {
return "中年";
} else {
return "老年";
}
})));
for (Map.Entry<Employee.Status, Map<String, List<Employee>>> statusMapEntry : collect1.entrySet()) {
System.out.println(statusMapEntry.getKey() + ":" + statusMapEntry.getValue().entrySet());
}
}
5.分区
@Test
public void test9(){
Map<Boolean, List<Employee>> collect = employees.stream().collect(Collectors.partitioningBy((e) -> e.getSalary() > 8000));
for (Map.Entry<Boolean, List<Employee>> booleanListEntry : collect.entrySet()) {
System.out.println(booleanListEntry.getKey() + ":" + booleanListEntry.getValue());
}
}
4.并行流与顺序流
- 并行流是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流
- Java8中将并行流进行了优化,可以更方便的对数据进行并行操作,Stream API可以声明性地通过parallel()与sequential()在并行流与顺序流之间进行切换
Fork/Join框架
- 注意:需要继承RecursiveTask
- 概念:在必要的情况下将一个大任务,进行拆分(fork)成若干个小任务,拆到不可再拆时,再将一个个的小任务运算的结果进行join汇总
- Fork/Join框架与传统线程池的区别
- 1.Fork/Join框架采用工作窃取模式(work-stealing)
- 即:当执行新的任务时它可以将其拆分,分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中
- 2.相对于一般的线程池实现,fork/join框架的优势体现在对其中包含的任务的处理方式上,在一般的线程池中,如果一个线程正在执行的任务由于某些原因无法继续运行,那么该线程会处于等待状态;而在fork/join框架实现中,如果某个子问题由于等待另外一个子问题的完成而无法继续运行,那么处理该子问题的线程会主动寻找其他尚未运行的子问题来执行,这种方式减少了线程的等待时间,提高了性能
package domains;
import java.util.concurrent.RecursiveTask;
public class ForkJoinCalculate extends RecursiveTask<Long> {
private static final long serialVersionUID = -8301484471666236858L;
private long start;
private long end;
private static final long THRESHOLD = 10000;
public ForkJoinCalculate(long start, long end) {
this.start = start;
this.end = end;
}
@Override
protected 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();
}
}
}
import domains.ForkJoinCalculate;
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;
public class TestForkJoin {
@Test
public void test1(){
Instant start = Instant.now();
ForkJoinPool pool = new ForkJoinPool();
ForkJoinTask<Long> task = new ForkJoinCalculate(0,1000000000L);
Long sum = pool.invoke(task);
System.out.println("累加和为:" + sum);
Instant end = Instant.now();
System.out.println("消耗时间为:" + Duration.between(start, end).toMillis());
}
@Test
public void test2(){
Instant start = Instant.now();
long sum = 0L;
for (int i = 0; i < 1000000000L; i++) {
sum += i;
}
System.out.println("累加和为:" + sum);
Instant end = Instant.now();
System.out.println("消耗时间为:" + Duration.between(start, end).toMillis());
}
@Test
public void test3(){
Instant start = Instant.now();
long sum = LongStream.rangeClosed(0, 1000000000L)
.parallel()
.reduce(0, Long::sum);
System.out.println("累加和为:" + sum);
Instant end = Instant.now();
System.out.println("消耗时间为:" + Duration.between(start, end).toMillis());
}
}
5.Optional类
- java.util.Optional类是一个容器类,代表一个值存在或不存在
- 原来用null表示一个值不存在,现在Optional可以更好的表达这个概念,并且可以避免空指针异常
package domains;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Godness {
private String name;
}
package domains;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Man {
private Godness godness;
}
package domains;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Optional;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class NewMan {
private Optional<Godness> godness = Optional.empty();
}
import domains.Employee;
import domains.Godness;
import domains.Man;
import domains.NewMan;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class TestOptional {
@Test
public void test1(){
Optional<Employee> optional = Optional.of(new Employee());
Employee employee = optional.get();
System.out.println(employee);
Optional<Object> o = Optional.ofNullable(null);
if(o.isPresent()){
System.out.println(o.get());
}
Optional<Employee> objectOptional = Optional.ofNullable(null);
System.out.println(objectOptional.orElse(new Employee(25)));
System.out.println(objectOptional.orElseGet(() -> new Employee("李四",3,35.5, Employee.Status.BUSY)));
Optional<Employee> employee1 = Optional.ofNullable(new Employee("李四",3,35.5, Employee.Status.BUSY));
Optional<String> optional1 = employee1.map(Employee::getName);
System.out.println(optional1.get());
Optional<String> s = employee1.flatMap((e) -> Optional.of(e.getName()));
System.out.println(s.get());
List<Employee> employees = Arrays.asList(
new Employee("张三",8,100, Employee.Status.BUSY),
new Employee("李四",12,500, Employee.Status.BUSY),
new Employee("王五",18,3000, Employee.Status.FREE),
new Employee("赵六",24,8000, Employee.Status.FREE),
new Employee("赵九",24,6000, Employee.Status.FREE),
new Employee("田七",35,15000, Employee.Status.VOCATION),
new Employee("吴八",40,25000, Employee.Status.FREE)
);
Optional<Employee> optional2 = Optional.ofNullable(employees.get(5)).filter(e -> e.getAge() > 24);
System.out.println(optional2.get());
}
@Test
public void test2(){
Man man = new Man();
String godnessName = getGodnessName2(Optional.ofNullable(null));
System.out.println(godnessName);
}
public String getGodnessName(Man man){
if(man != null){
Godness godness = man.getGodness();
if(godness != null){
return godness.getName();
}
}
return "测试";
}
public String getGodnessName2(Optional<NewMan> man){
return man.orElse(new NewMan())
.getGodness()
.orElse(new Godness("测试"))
.getName();
}
}
6.接口中的默认方法与静态方法
- Java8中允许接口中包含具有具体实现的方法,该方法称为默认方法,默认方法使用default关键字修饰
接口默认方法的类优先原则
- 若一个接口定义了一个默认方法,而另外一个父类或接口又定义了一个同名的方法时
- 1.选择父类中的方法。如果一个父类提供了具体的实现,那么接口中具有相同名称和参数的默认方法会被忽略
- 2.接口冲突。如果一个父接口提供一个默认方法,而另一个父接口也提供了一个具有相同名称和参数列表的方法(不管方法是否是默认方法),那么实现类必须选择一个接口或者覆盖该方法来解决冲突
package dao;
public interface MyFun1 {
default String getName(){
return "myFun1";
}
static void show(){
System.out.println("接口中的静态方法");
}
}
package dao;
public interface MyFun2 {
default String getName(){
return "myFun2";
}
}
package domains;
public class MyClassFun {
public String getName(){
return "MyClassFun";
}
}
package domains;
import dao.MyFun1;
import dao.MyFun2;
public class SubClass implements MyFun1, > MyFun2 {
@Override
public String getName() {
return MyFun1.super.getName();
}
}
import domains.SubClass;
import org.junit.Test;
public class TestDefault {
@Test
public void test1(){
SubClass subClass = new SubClass();
String name = subClass.getName();
System.out.println(name);
MyFun1.show()
}
}
7.传统时间格式化的线程安全问题
- java.util.Date() JDK1.0版本
- java.util.Calender() JDK1.1版本
- java.util.TimeZone()
- java.text.SimpleDateFormat
- 声明不规范,不安全
8.新时间与日期API
- java.time包下
- java.time.
- java.time.format
- java.time.temporal
- java.time.zone
- 不可变,会产生新的实例
- 线程安全
9.重复注解与类型注解