1. Lambda表达式
1.1 什么是函数式接口?
有且仅有一个抽象方法的接口。
1.2 怎么判断一个接口是不是函数式接口?
使用@FunctionalInterface进行标记判,标记不报错则为函数式接口,例如创建线程的Runnable接口。
package com.example.javaee.newfeatures.lambda.inf;
@FunctionalInterface
public interface Usb {
public void print(String str);
}
1.3 @FunctionalInterface注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}
1.4 java8中声明的函数式接口所在包
java.util.function
1.5 四大基本函数式接口
接口 | 对应方法 | |
消费型 | Consumer<T> | void accept(T t); |
供给型 | Supplier<T> | T get(); |
函数型 | Function<T, R> | R apply(T t); |
判断型 | Predicate<T> | boolean test(T t); |
1.6 Lambda的本质是什么?
Lambda本质是一种匿名实现类对象。
package com.example.javaee.newfeatures.lambda.inf;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
/**
*
* @author
*/
@SpringBootTest
class UsbTest {
/**
* 例如线程的runnable接口的使用,要创建接口的匿名实现类
*/
@Test
public void testCommon(){
Usb usb = new Usb(){
@Override
public void print(String str) {
System.out.println(str);
}
};
usb.print("接口匿名实现类对象");
}
/**
* Lambda实现
*/
@Test
public void testLambda(){
Usb usb = str -> System.out.println(str);
usb.print("Lambda实现");
}
/**
* 方法引用
*/
@Test
public void testMethodReference(){
Usb usb = System.out::println;
usb.print("方法引用实现");
}
}
1.7 Lambda的具体使用
给函数式接口提供实例时,可以考虑Lambda表达式。
2. Stream API
2.1 什么是Stream API,有什么用?
是一系列用于专门操作集合中数据的API,是面向 CPU的。
2.2 Stream API的执行流程
实例化——>中间操作——>终止操作
2.3 Stream API所在的包
java.util.stream
2.4 Stream 实例化
@Test
public void testCreateStream(){
/**
* 集合
*/
//顺序流
Stream<Employee> stream = list.stream();
//并行流
Stream<Employee> parallelStream = list.parallelStream();
/**
* 数组
*/
Stream<Employee> arrStream = Arrays.stream(objs);
Stream<String> streamOf = Stream.of("AA", "BB", "CC");
}
2.5 Stream 中间操作
/**
* 过滤
*
*/
@Test
public void testFilter(){
list.stream().filter(obj -> obj.getSalary() > 7000).forEach(System.out::println);
}
/**
* 截断
*/
@Test
public void testLimit(){
list.stream().limit(2).forEach(System.out::println);
}
/**
* 跳过
*/
@Test
public void testSkip(){
list.stream().skip(2).forEach(System.out::println);
}
/**
* 去重 根据hashCode() 和 equals()去重
*/
@Test
public void testDistinct(){
list.stream().distinct().forEach(System.out::println);
}
/**
* 映射
*/
@Test
public void testMap(){
Arrays.stream(strArr).map(String::toLowerCase).forEach(System.out::println);
}
/**
* 排序
*/
@Test
public void testSorted(){
//自然排序
Arrays.stream(strArr).sorted().forEach(System.out::println);
//定制排序
Arrays.stream(strArr).sorted((s1, s2) -> -s1.compareTo(s2)).forEach(System.out::println);
}
2.6Stream 终止操作
2.6.1 查找遍历
/**
* 全部匹配
*/
@Test
public void testAllMatch(){
System.out.println(list.stream().allMatch(emp -> emp.getAge() > 18));
}
/**
* 至少一个
*/
@Test
public void testAnyMatch(){
System.out.println(list.stream().anyMatch(emp -> emp.getAge() > 18));
}
/**
* 返回第一个元素
*/
@Test
public void testFindFirst(){
System.out.println(list.stream().findFirst().get());
}
/**
* 计数
*/
@Test
public void testCount(){
System.out.println(list.stream().count());
}
/**
* 最大值
*/
@Test
public void testMax(){
System.out.println(list.stream().max((e1,e2) -> (int) Math.round(e1.getSalary() - e2.getSalary())));
}
/**
* 最小值
*/
@Test
public void testMin(){
System.out.println(list.stream().min((e1,e2) -> (int) Math.round(e1.getSalary() - e2.getSalary())));
}
/**
* 遍历
*/
@Test
public void testForEach(){
list.stream().forEach(System.out::println);
}
/**
* 遍历 @since 1.8
*/
@Test
public void testForEachNew(){
list.forEach(System.out::println);
}
2.6.2 归约收集
/**
* 归约
*/
@Test
public void testForReduce(){
System.out.println(integers.stream().reduce(0, Integer::sum));
}
/**
* 收集
*/
@Test
public void testForCollect(){
list.stream().filter(emp -> emp.getSalary()>5000).collect(Collectors.toList()).forEach(System.out::println);
}
2.7Stream使用说明
- Stream只是一系列对于数据处理的操作,自己并不会 存储数据。
- Stream不会改变源对象。
- Stream的 操作是延迟操作,需要执行终止操作才会执行。
- Stream一旦执行了终止操作,就不会再执行中间操作和终止操作,否则会报异常java.lang.IllegalStateException: stream has already been operated upon or closed
3. 新的try—catch
/**
* JDK7之前的try——catch
*/
@Test
public void test(){
FileWriter fileWriter = null;
BufferedWriter bufferedWriter = null;
try {
fileWriter = new FileWriter("D://aaa.txt");
bufferedWriter = new BufferedWriter(fileWriter);
bufferedWriter.write("Hello");
} catch (IOException e) {
throw new RuntimeException(e);
}finally{
try {
if(bufferedWriter != null){
bufferedWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* JDK7的try——catch
* 要求资源实现 AutoCloseable @since 1.7
*/
@Test
public void testJDK7(){
try (FileWriter fileWriter =new FileWriter("D://aaa.txt");
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
){
bufferedWriter.write("Hello");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* JDK9
*/
@Test
public void testJDK9(){
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(System.out);
try (inputStreamReader;outputStreamWriter
){
} catch (IOException e) {
throw new RuntimeException(e);
}
}
4.类型推断
/**
* @since JDK10
* 类型推断
*/
@Test
public void testVar(){
var lists = new ArrayList<>();
lists.add("1");
for (var list : lists) {
System.out.println(list);
}
var iterator = lists.iterator();
}
5.新的instanceof
/**
* JDK14之前
*/
@Test
public void testInstanceof(){
Object obj = new String("hello");
if (obj instanceof String) {
String str = (String) obj;
System.out.println("String 类型");
}else {
System.out.println("非 String 类型");
}
}
/**
* JDK14之后
*/
@Test
public void testNewInstanceof(){
Object obj = new String("hello");
if (obj instanceof String str) {
System.out.println("String 类型");
}else {
System.out.println("非 String 类型");
}
}
6.Switch新特性
新的Switch代码块中,我们可以使用 -> 操作符代替省略break,可以使用变量接收Switch返回的值,加入了yeild关键字,用于返回指定的数据,结束代码块,同时也引进了模式匹配。
/**
* 使用 -> 省略break
* 使用变量接收switch表达式的值
*/
@Test
public void testNewSwitch(){
Season season = Season.WINTER;
String expression = switch (season){
case SPRING -> "SPRING";
case SUMMER -> "SUMMER";
case AUTUMN,WINTER -> "AUTUMN AND WINTER";
};
System.out.println(expression);
}
/**
* yield可以返回指定的数据,结束switch表达式
* break 用于无返回值 结束switch表达式
*/
@Test
public void testNewSwitch1(){
Season season = Season.WINTER;
String expression = switch (season){
case SPRING :
yield "SPRING";
case SUMMER :
yield "SUMMER";
case AUTUMN,WINTER :
yield "AUTUMN AND WINTER";
};
System.out.println(expression);
}
/**
* switch表达式模式匹配
*/
@Test
public void testNewSwitch2(){
Object obj = new String("hello");
String expression = switch (obj){
case Integer integer :
yield "Integer:" + integer;
case Double dou :
yield "Double:" + dou;
case String str:
yield "String:" +str;
default :
yield obj.toString();
};
System.out.println(expression);
}
7. 代码块的使用
/**
* \ 取消换行
* \s 代表空格
*/
@Test
public void testBlock(){
String sql = """
select * from\s\
dual
where 1 = 1
""";
System.out.println(sql);
}
8. record类的使用
- record 可以避免编写构造器、访问器、equal方法、hashCode()、toString()。
- record中还可以定义静态变量、静态方法、构造器、实例方法。
- record本质是final类,不可被继承和使用abstract,属性也是final修饰的。
- 不能显示声明父类。
- record 不能替代java Bean 因为 java Bean 通常都是可变的,而 record 是不可变的。
public record Record(Integer id, String name){
}
class文件反编译的内容:
public record Record(Integer id, String name) {
public Record(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer id() {
return this.id;
}
public String name() {
return this.name;
}
}
9. 密封类
用于指定子类类型,哪些可以被继承,并且之类类型是final、sealed、non-sealed之一。
public sealed class Person permits Worker,Student,Teacher {}
final class Worker extends Person {}
non-sealed class Student extends Person {}
sealed class Teacher extends Person permits MathTeacher{}
final class MathTeacher extends Teacher {}
10. Optional类
Optional类是为了解决空指针异常。
@Test
public void testOptional(){
String language = "java";
String otherLanguage = "C";
language = null;
Optional<String> optional = Optional.ofNullable(language);
String finalLanguage = optional.orElse(otherLanguage);
System.out.println(finalLanguage);
}