JDK1.8新特性
发表于更新于
字数总计:8.3k阅读时长:36分钟阅读量: 成都
JDK1.8新特性
JDK1.8新特性简介
- 速度更快 - 优化底层源码,比如HashMap、ConcurrentHashMap
- 代码更少 - 添加新的语法Lambda表达式
- 强大的Stream API
- 便于并行
- 最大化减少空指针异常 - Optional
Lambda表达式
简介
Lambda是一个匿名函数(方法), 允许把函数作为一个方法的参数 。利用Lambda表达式可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。
一般都是优化匿名内部类
基础语法
无参数、无返回值的抽象方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class Test1 { @Test public void test01() {
I1 i1 = ()-> System.out.println("采用Lambda表达式的方式"); i1.method(); } } interface I1{ public void method(); }
|
一个参数、无返回值的抽象方法
1 2 3 4 5 6 7 8 9 10
| public class Test1 { @Test public void test01() { I1 i1 = (x)-> System.out.println("采用Lambda表达式的方式 " + x); i1.method(1000); } } interface I1{ public void method(int num1); }
|
多个参数、无返回值的抽象方法
1 2 3 4 5 6 7 8 9 10 11 12
| public class Test1 { @Test public void test01() { I1 i1 = (x,y,z)-> System.out.println("采用Lambda表达式的方式 " + x + y + z); i1.method(1000,2000,3000); } } interface I1{ public void method(int num1,int num2,int num3); }
|
多个参数、有返回值的抽象方法
1 2 3 4 5 6 7 8 9 10 11 12
| public class Test1 { @Test public void test01() { I1 i1 = (x,y,z)-> x+y+z; int result = i1.method(1000,2000,3000); System.out.println(result); } } interface I1{ public int method(int num1,int num2,int num3); }
|
注意点
- 重写方法的形参只有一个时,可以不加小括号
- Lambda表达式当中不允许声明一个与局部变量同名的参数或者局部变量
- Lambda表达式中访问外层的局部变量,外层的局部变量自动变成隐式常量,默认添加final
- 重写方法的形参同时加类型或同时不加类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class Test1 { @Test public void test01() { int x; int num = 10; I1 i1 = x -> System.out.println(x + (num++)); i1.method(1000); I2 i2 = (int x,int y) -> { int result = x+y; return result; }; int result = i2.method(10, 20); System.out.println(result); } } interface I1{ public void method(int num1); } interface I2{ public int method(int num1,int num2); }
|
练习
1.调用Collections.sort()方法,通过定制排序比较两个Student对象(先按年龄比较,年龄相同按照薪资比较),使用Lambda表达式作为参数传递
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public class Test1 { @Test public void 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)); Collections.sort(stuList, (a,b)-> { if(a.getAge() == b.getAge()){ return Double.compare(a.getSalary(),b.getSalary()); } return a.getAge()-b.getAge(); }); for (Student stu : stuList) { System.out.println(stu); } } } enum Course{ JAVA,HTML,PYTHON; } class Student{ private String name; private int age; private double salary; private Course course; ... }
|
2.创建I1接口,创建抽象方法:public String getValue(String str),在测试类中编写方法使用接口作为参数,将一个字符串转为大写,并作为方法的返回值
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Test1 { @Test public void test01() { String strHandler = strHandler("abc", x-> x.toUpperCase()); System.out.println(strHandler); } public static String strHandler(String str,I1 i1){ return i1.getValue(str); } } interface I1{ public String getValue(String str); }
|
3.创建I1<T,R>接口,泛型T为参数,R为返回值,创建抽象方法:public R add(T t1,T t2),在测试类中编写方法使用接口作为参数,计算两个long类型的和
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Test1 { @Test public void test01() { Long addLong = addLong(100L, 200L, (x,y)-> x+y); System.out.println(addLong); } public static Long addLong(Long l1,Long l2,I1<Long,Long> i1){ return i1.add(l1, l2); } } interface I1<T,R>{ public R add(T t1,T t2); }
|
函数式接口
简介
函数式接口是指仅仅只包含一个抽象方法的接口,jdk1.8提供了一个@FunctionalInterface注解来定义函数式接口,如果我们定义的接口不符合函数式的规范便会报错。配合Lambda表达式一起使用
四大核心函数式接口
函数式接口 | 参数类型 | 返回类型 | 用途 |
---|
Consumer消费型接口 | T | void | void accept(T t); |
Supplier供给型接口 | void | T | T get(); |
Function<T, R> 函数型接口 | T | R | R apply(T t); |
Predicate断言型接口 | T | boolean | booelan test(T t); |
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); |
UnaryOperatorextends Function<T, T> | T | T | 对类型为T的对象进行一元运算,并返回T类型的结果。包含方法为T apply(T t); |
BinaryOperatorextends BiFunction<T,T,T> | T,T | T | 对类型为T的对象进行二元运算,并返回T类型的结果。包含方法为T apply(T t1,T t2); |
ToIntFunctionToLongFunctionToDoubleFunction | T | int long double | 分别计算int、long、double值的函数 |
IntFunctionLongFunctionDoubleFunction | int long double | R | 参数为int、long、double类型的函数 |
应用场景:当项目中需要一个接口,并且该接口中只有一个抽象方法,就没必要去创建新的接口,直接选择Java提供的使用合适的函数式接口即可
方法、构造方法和数组引用
方法、构造方法和数组引用就是Lambda的另一种表现形式
方法引用
若Lamdba表达式中的内容由方法已经实现了,可以使用方法引用这个技能
当你需要使用方法引用时,目标引用放在分隔符::前,方法的名称放在后面
对象::实例方法
Lambda表达式中调用方法的参数类型和返回值必须和函数式接口中的抽象方法一致
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class Test1 { @Test public void test01() {
PrintStream ps = System.out; I1 i1 = ps::println; i1.method("abcd"); } } interface I1{ public void method(String str); }
|
类名::静态方法
Lambda表达式中调用方法的参数类型和返回值必须和函数式接口中的抽象方法一致
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Test1 { @Test public void test01() {
Comparator<Integer> com = Integer::compare; int compare = com.compare(10, 20); System.out.println(compare); } }
|
类名::实例方法
Lambda表达式参数列表中第一个参数必须是实例方法的调用者
Lambda表达式参数列表中第二个参数必须是实例方法的参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class Test1 { @Test public void test01() {
I1<String> i1 = String::equals; boolean method = i1.method("abc", "abc"); System.out.println(method); } } interface I1<T>{ public boolean method(T t1,T t2); }
|
构造方法引用
类名::new
需要调用的构造方法的参数列表必须和函数式接口中抽象方法的参数列表一致
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class Test1 { @Test public void test01() { I1<Student> i1 = Student::new;
System.out.println(i1.method("桥本有菜",24,8888,Course.JAVA)); } } interface I1<T>{
public T method(String name,int age,double salary,Course course); } enum Course{ JAVA,HTML,PYTHON; } class Student{ private String name; private int age; private double salary; private Course course; ... }
|
数组引用
语法格式:type[]::new
1 2 3 4 5 6 7 8 9 10 11
| public class Test1 { @Test public void test01() { I1<String[]> i1 = String[]::new; System.out.println(Arrays.toString(i1.method(10))); } } interface I1<T>{ public T method(int capacity); }
|
Stream
简介
Stream(流)是数据渠道,用于操作数据源(集合、数组等),生成元素序列。换言之,集合是存储数据的容器,流使用操作这些数据的
Stream可以对集合进行非常复杂的查找、过滤、映射数据等操作,类似于SQL执行数据库查询。Stream提供了一种高效且易于使用的处理数据的方式
注意:
- Stream不会存储数据
- Stream不会改变源数据,通过一系列操作数据源会返回一个持有结果的新Stream
- Stream操作是延迟执行的,意味着流会等到需要结果的时候才执行
执行步骤
- 创建Stream:通过数据源(集合、数组等)获取一个Stream
- 中间操作:中间操作链,对源数据的数据进行处理
- 终止操作:执行中间操作,并产生结果
创建Stream
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class Test1 { @Test public void test01() { List<String> list = new ArrayList<>(); Stream<String> stream1 = list.stream(); String[] strs = new String[10]; Stream<String> stream2 = Arrays.stream(strs); Stream<String> stream3 = Stream.of("aaa","bbb","ccc"); 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()方法去除重复元素 |
如果没有终止操作,中间操作就不会被调用,终止操作时一次性全部处理,这种称为惰性求值/延迟加载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| 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)); @Test public void test01() { Stream<Student> stream = stuList.stream().filter((x)-> { System.out.println("中间操作"); return x.getSalary()>5000; }); stream.forEach(System.out::println); } @Test public void test02() { Stream<Student> stream = stuList.stream().filter((x)-> { System.out.println("短路"); return x.getSalary()>5000; }).limit(3); stream.forEach(System.out::println); } @Test public void test03() { Stream<Student> stream = stuList.stream(). filter((x)-> x.getSalary()>5000). skip(1); stream.forEach(System.out::println); } @Test public void test04() { Stream<Student> stream = stuList.stream(). filter((x)-> x.getSalary()>5000). distinct();
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) | 将流中的流整合(整合成平面/平铺流) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| 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)); @Test public void test01() { nameList.stream().map((str)-> str.charAt(0)).forEach(System.out::println); stuList.stream().map((stu)-> stu.getName()).forEach(System.out::println); } @Test public void test02() {
Stream<Stream<Character>> stream = nameList.stream(). map(Test1::getCharacterStream); stream.forEach((sm) -> { sm.forEach(System.out::println); });
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; ... }
|
中间操作 - 排序
方法 | 解释 |
---|
sorted() | 使用元素原有排序规则 - Comparable |
sorted(Comparator<? super T> comparator) | 使用自定义排序规则 - Comparator |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| 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("吴八", 31, 3000,Course.PYTHON)); @Test public void test01() { stuList.stream().sorted().forEach(System.out::println); } @Test public void test02() { stuList.stream().sorted((e1,e2)->{ if(e1.getSalary() == e2.getSalary()){ return 1; } return (int)(e1.getSalary() - e2.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) | 返回流中最小值 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| 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("吴八", 31, 3000,Course.PYTHON)); @Test public void test01() { boolean allMatch = stuList.stream().allMatch((stu) -> stu.getSalary()>5000); System.out.println(allMatch); boolean anyMatch = stuList.stream().anyMatch((stu) -> stu.getSalary()>5000); System.out.println(anyMatch); boolean noneMatch = stuList.stream().noneMatch((stu) -> stu.getSalary()>5000); System.out.println(noneMatch); Optional<Student> findFirst = stuList.stream(). sorted((stu1,stu2)->Double.compare( stu1.getSalary(),stu2.getSalary())). findFirst(); Student stu = findFirst.get(); System.out.println(stu); Optional<Student> findAny = stuList.stream().findAny(); Student stu = findAny.get(); System.out.println(stu); long count = stuList.stream().count(); System.out.println(count); Optional<Student> max = stuList.stream(). max((stu1,stu2)->Double.compare(stu1.getSalary(),stu2.getSalary())); System.out.println(max.get()); Optional<Student> min = stuList.stream(). min((stu1,stu2)->Double.compare(stu1.getSalary(),stu2.getSalary())); System.out.println(min.get()); } } 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 , BinaryOperatoraccumulator) | 参数:(初始值,结合逻辑) |
reduce(BinaryOperatoraccumulator) | 参数:(结合逻辑) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| public class Test1 {
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("李四", 36, 7200,Course.JAVA)); @Test public void test01() { Integer reduce = numList.stream(). reduce(0, (x,y)->x+y); System.out.println(reduce); } @Test public void test02() { Optional<Double> reduce = stuList.stream(). map(Student::getSalary).reduce(Double::sum); Double sumSalary = reduce.get(); System.out.println(sumSalary); } } 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集合中 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
| 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));
@Test public void test01() { List<String> list = stuList.stream(). map(Student::getName). collect(Collectors.toList()); list.forEach(System.out::println);
Set<String> set = stuList.stream(). map(Student::getName).collect(Collectors.toSet()); set.forEach(System.out::println);
HashSet<String> hashSet = stuList.stream(). map(Student::getName).collect(Collectors.toCollection(HashSet::new)); hashSet.forEach(System.out::println); } @Test public void test02() { Long count = stuList.stream(). map(Student::getName).collect(Collectors.counting()); System.out.println(count);
Double avg = stuList.stream(). collect(Collectors.averagingDouble(Student::getSalary)); System.out.println(avg);
Double sum = stuList.stream(). collect(Collectors.summingDouble(Student::getSalary)); System.out.println(sum);
Optional<Double> max = stuList.stream().map(Student::getSalary). collect(Collectors.maxBy(Double::compareTo)); System.out.println(max.get());
Optional<Double> min = stuList.stream().map(Student::getSalary). collect(Collectors.minBy(Double::compareTo)); System.out.println(min.get());
Optional<Student> maxStu = stuList.stream(). collect(Collectors.maxBy( (stu1,stu2)-> (int)(stu1.getSalary()-stu2.getSalary()))); System.out.println(maxStu.get());
Optional<Student> minStu = stuList.stream(). collect(Collectors.maxBy( (stu1,stu2)-> -(int)(stu1.getSalary()-stu2.getSalary()))); System.out.println(minStu.get()); } @Test public void test03() { Map<Course, List<Student>> map = stuList.stream().collect( Collectors.groupingBy(Student::getCourse)); System.out.println(map); } @Test public void test04() { 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 "老年"; } }))); System.out.println(map); } @Test public void test05() { Map<Boolean, List<Student>> map = stuList.stream().collect( Collectors.partitioningBy((stu) -> stu.getSalary()>5000)); System.out.println(map); } @Test public void test06() { DoubleSummaryStatistics collect = stuList.stream().collect( Collectors.summarizingDouble(Student::getSalary)); System.out.println(collect.getSum()); System.out.println(collect.getAverage()); System.out.println(collect.getMax()); System.out.println(collect.getMin()); } @Test public void test07() { String str1 = stuList.stream().map(Student::getName).collect( Collectors.joining()); System.out.println(str1); String str2 = stuList.stream().map(Student::getName).collect( Collectors.joining(",")); System.out.println(str2); String str3 = stuList.stream().map(Student::getName).collect( Collectors.joining(",","--","--")); System.out.println(str3); } } 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()-顺序流 之间进行切换。
注意
- 默认为顺序流/串行流
- 并行流一般在大数据搜索里使用到
- JDK1.8之前也有并行流,叫做Fork/Join并行计算框架
1 2 3 4 5 6 7 8 9 10 11
| public class Test1 { @Test public void test01() { OptionalLong reduce = LongStream. range(0, 10000001L). parallel(). reduce(Long::sum); System.out.println(reduce); } }
|
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 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| public class Test1 { @Test public void test01() {
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()); boolean bool = true; stu = op.orElseGet(()->{ if(bool){ return new Student("吴彦祖", 26, 8888, Course.JAVA); }else{ return new Student("麻生希", 26, 8888, Course.JAVA); } }); Optional<String> map = op.map(Student::getName); System.out.println(map.get()); 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修饰的方法,此方法可以让接口的实现类所调用,而接
口中的静态方法直接用接口名调用即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class Test1 { @Test public 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{}
|
接口默认方法的”类优先”原则:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class Test1 { @Test public void test01() { MyClass myClass = new MyClass(); MyClass.method(); } } interface I1{ default void method(){ System.out.println("I1接口中的默认方法"); } } class Father { public void method(){ System.out.println("Father类中的默认方法"); } } class MyClass extends Father implements I1 {}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class Test1 { @Test public void test01() { MyClass myClass = new MyClass(); myClass.method(); } } interface I1{ default void method(){ System.out.println("I1接口中的默认方法"); } } interface I2{ default void method(){ System.out.println("I2接口中的默认方法"); } } class MyClass implements I1,I2 { @Override public void method() { I2.super.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 | | 针对时区操作的包 |
日期时间类、时间戳、间隔类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| public class Test1 { @Test public void test01() {
LocalDateTime ldt1 = LocalDateTime.now(); System.out.println(ldt1);
LocalDateTime ldt2 = LocalDateTime.of(2020, 1, 23, 8, 30, 10, 10); System.out.println(ldt2);
LocalDateTime ldt3 = ldt1.plusYears(2); System.out.println(ldt3);
LocalDateTime ldt4 = ldt3.minusMonths(2);
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()); } @Test public void test02() {
Instant now1 = Instant.now(); System.out.println(now1);
OffsetDateTime odt = now1.atOffset(ZoneOffset.ofHours(8)); System.out.println(odt);
System.out.println(now1.toEpochMilli());
Instant now2 = Instant.ofEpochSecond(1); System.out.println(now2); } @Test public void test03() throws InterruptedException {
Instant now1 = Instant.now(); Thread.sleep(1000); Instant now2 = Instant.now(); Duration duration1 = Duration.between(now1, now2); System.out.println(duration1.toMillis()); System.out.println("-----------------------------"); LocalTime lt1 = LocalTime.now(); Thread.sleep(1000); LocalTime lt2 = LocalTime.now(); Duration duration2 = Duration.between(lt1, lt2); System.out.println(duration2.toMillis()); } @Test public void test04() throws InterruptedException { LocalDate ld1 = LocalDate.now(); Thread.sleep(1000); LocalDate ld2 = LocalDate.of(2020, 12, 31); Period period = Period.between(ld1, ld2); System.out.println(period.getYears()); System.out.println(period.getMonths()); System.out.println(period.getDays()); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class Test1 { @Test public void test01() { LocalDateTime ldt1 = LocalDateTime.now(); DateTimeFormatter dtf1 = DateTimeFormatter.ISO_LOCAL_DATE_TIME; String strDateTime1 = ldt1.format(dtf1); System.out.println(strDateTime1); DateTimeFormatter dtf2 = DateTimeFormatter. ofPattern("yyyy年MM月dd日 HH:mm:ss"); String strDateTime2 = ldt1.format(dtf2); System.out.println(strDateTime2); LocalDateTime parse = LocalDateTime.parse("2020年03月12日 11:04:14", dtf2); System.out.println(parse); } }
|
时间矫正器类-TemporalAdjuster
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public class Test1 { @Test public void test01() { LocalDateTime ldt1 = LocalDateTime.now(); LocalDateTime ldt2 = ldt1.withMonth(10); System.out.println(ldt2); LocalDateTime ldt3 = ldt1.with(TemporalAdjusters.next(DayOfWeek.SUNDAY)); System.out.println(ldt3); LocalDateTime ldt4 = ldt1.with((temporal)->{ LocalDateTime ldt = (LocalDateTime) temporal; DayOfWeek week = ldt.getDayOfWeek(); if(week.equals(DayOfWeek.FRIDAY)){ return ldt.plusDays(3); }else if(week.equals(DayOfWeek.SATURDAY)){ return ldt.plusDays(2); }else{ return ldt.plusDays(1); } }); System.out.println(ldt4); } }
|
时区类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class Test1 { @Test public void test01() { Set<String> set = ZoneId.getAvailableZoneIds(); for (String str : set) { System.out.println(str); } LocalDateTime ldt1 = LocalDateTime.now(ZoneId.of("Asia/Tokyo")); System.out.println(ldt1); LocalDateTime ldt2 = LocalDateTime.now(ZoneId.of("Asia/Tokyo")); ZonedDateTime zonedDateTime = ldt2.atZone(ZoneId.of("Asia/Tokyo")); System.out.println(zonedDateTime); } }
|
重复注解及类型注解
jdk1.8开始可以重复注解
ps:一个类可有多个同样的注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.TYPE_PARAMETER;
import java.lang.annotation.Annotation; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Method;
import org.junit.Test;
@Author(name="何老师") @Author(name="苍老师") public class Test1 { @Test public void test01() throws Exception{ Class<Test1> ct = Test1.class; Author[] as = ct.getAnnotationsByType(Author.class); for (Author a : as) { System.out.println(a.name()); } Method m = ct.getMethod("method", String.class); Annotation[][] parameterAnnotations = m.getParameterAnnotations(); for (Annotation[] annotations : parameterAnnotations) { for (Annotation an : annotations) { System.out.println(an); } } } public static void method(@Author(name="波老师") String str){} }
@Target(TYPE) @Retention(RetentionPolicy.RUNTIME) @interface Authors{ Author[] value(); }
@Repeatable(Authors.class) @Target({TYPE, PARAMETER,TYPE_PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @interface Author{ String name(); }
|