lambda形参列表(要重写的接口中的抽象方法的形参列表) -> lambda体(接口的实现类要重写的方法的方法体)
一方面,lambda作为接口的实现类的对象;另一方面,lambda是一个匿名函数
是什么?
接口中仅仅声明有一个抽象方法
只有给函数式接口提供实现类的对象时,我们才可以使用lambda表达式
4个基本的函数式接口
接口 | 对应抽象方法 | |
---|---|---|
消费型接口 | Consumer | void accept(T t) |
供给型接口 | Supplier | T get() |
函数型接口 | Function |
R apply(T t) |
判断型接口 | Predicate | boolean test(T t) |
package com.atguigu.newfeatures;
import org.junit.Test;
import java.util.Comparator;
import java.util.function.Consumer;
public class LambdaTest {
//格式1:无参 无返回值
@Test
public void test1() {
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("我爱天安门");
}
};
r1.run();
System.out.println("=============================");
Runnable r2 = () -> {
System.out.println("我爱天安门");
};
r2.run();
}
//格式2:有参 无返回值
@Test
public void test2() {
Consumer<String> con = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
con.accept("谎言真话的区别是什么");
System.out.println("=============================");
Consumer<String> con1 = (String s) -> {
System.out.println(s);
};
con1.accept("定义不一样");
}
//格式3:数据类型可以由编译器推断得出
@Test
public void test3() {
Consumer<String> c1 = (String s) -> {
System.out.println(s);
};
c1.accept("你想干什么,如果大学可以重来");
System.out.println("=============================");
Consumer<String> c2 = (s) -> {
System.out.println(s);
};
c2.accept("我想睡觉");
}
//格式4:只需要一个参数时,参数的小括号可以省略
@Test
public void test4() {
Consumer<String> c1 = (String s) -> {
System.out.println(s);
};
c1.accept("关于我是谁,双枪会给出答案");
System.out.println("=============================");
Consumer<String> c2 = s -> {
System.out.println(s);
};
c2.accept("关于我是谁,双枪会给出答案");
}
//格式5:有两个及以上的参数,多条执行语句,有返回值
@Test
public void test5() {
Comparator<Integer> con1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
}
};
System.out.println(con1.compare(12,21));
System.out.println("=============================");
Comparator<Integer> con2 = (o1, o2) -> {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
};
System.out.println(con2.compare(12,21));
}
//格式6:lambda体仅有一条语句,return与大括号都可以省略
@Test
public void test6() {
Comparator<Integer> con1 = (o1, o2) -> {
return o1.compareTo(o2);
};
System.out.println(con1.compare(12,21));
System.out.println("=============================");
Comparator<Integer> con2 = (o1, o2) -> o1.compareTo(o2);
System.out.println(con2.compare(12,16));
}
}
类(或者对象) :: 方法名
方法引用作为了函数式接口的实例
1.对象 :: 实例方法
要求:函数式接口的抽象方法**a(get)与其内部实现时调用的对象的某个方法b(getName)**的形参列表和返回值类型都相同(满足多态)。
注意:b是非静态方法,需要对象调用
2.类 :: 静态方法
要求:函数式接口的抽象方法a与其内部实现时调用的类的某个静态方法b的形参列表和返回值类型都相同(满足多态)。
注意:b是静态方法,需要类调用
3.类 :: 实例方法
要求:函数式接口中的抽象方法a与其内部实现时调用的对象的某个方法b的返回值相同。
同时,抽象方法a中有n个参数,方法b中有n-1个参数,而且抽象方法a的第一个参数作为方法b的调用者,抽象方法a的后n-1个参数与方法b的n-1个参数的类型相同(或一致)
注意:b是非静态方法,需要对象调用。形式上,写出对象a所属的类
package com.atguigu.newfeatures;
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 MethodsTest {
//情况1:对象 :: 实例方法
@Test
public void test1() {
Consumer<String> con1 = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
con1.accept("藏好了吗,再给你一首歌的时间");
Consumer<String> con2 = s -> System.out.println(s);
con2.accept("藏好了吗,再给你一首歌的时间");
Consumer<String> con3 = System.out::println;
con3.accept("藏好了吗,再给你一首歌的时间");
}
@Test
public void test2() {
Hero mk = new Hero("暗影游猎", 1);
Supplier<String> sup1 = new Supplier<String>() {
@Override
public String get() {
return mk.getName();
}
};
System.out.println(sup1.get());
Supplier<String> sup2 = () -> mk.getName();
System.out.println(sup2.get());
Supplier<String> sup3 = mk::getName;
System.out.println(sup3.get());
}
//情况2:类 :: 实例方法
@Test
public void test3() {
Comparator<Integer> c1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1, o2);
}
};
System.out.println(c1.compare(12, 21));
Comparator<Integer> c2 = (o1, o2) -> Integer.compare(o1, o2);
System.out.println(c2.compare(25, 66));
Comparator<Integer> c3 = Integer::compare;
System.out.println(c3.compare(89, 88));
}
@Test
public void test4() {
Function<Double, Long> fun1 = new Function<Double, Long>() {
@Override
public Long apply(Double aDouble) {
return Math.round(aDouble);
}
};
Function<Double, Long> fun2 = aDouble -> Math.round(aDouble);
Function<Double, Long> fun3 = Math::round;
}
//情况3:类 :: 实例方法
@Test
public void test5() {
Comparator<String> com1 = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
};
System.out.println(com1.compare("EstarPro", "KSG"));
Comparator<String> com2 = (o1, o2) -> o1.compareTo(o2);
System.out.println(com2.compare("ag", "ttg"));
Comparator<String> com3 = String::compareTo;
}
@Test
public void test6() {
BiPredicate<String, String> biPredicate1 = new BiPredicate<String, String>() {
@Override
public boolean test(String s1, String s2) {
return s1.equals(s2);
}
};
System.out.println(biPredicate1.test("hero", "wolves"));
BiPredicate<String, String> biPredicate2 = (s1, s2) -> s1.equals(s2);
System.out.println(biPredicate2.test("edgm", "rngm"));
BiPredicate<String, String> biPredicate3 = String::equals;
System.out.println(biPredicate3.test("t", "u"));
}
@Test
public void test7() {
Hero al = new Hero("祈雪灵祝",2);
Function<Hero, String> fun1 = new Function<Hero, String>() {
@Override
public String apply(Hero hero) {
return hero.getName();
}
};
System.out.println(fun1.apply(al));
Function<Hero, String> fun2 = (hero -> hero.getName());
System.out.println(fun2.apply(al));
Function<Hero, String> fun3 = Hero::getName;
System.out.println(fun3.apply(al));
}
}
class Hero {
public String name;
public int id;
public Hero(String name, int id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
类名 :: new
数组名[] :: new
构造器引用
package com.atguigu.newfeatures;
import org.junit.Test;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
public class ConstructorTest {
@Test
public void test1() {
Supplier<Hero> supplier1 = new Supplier<Hero>() {
@Override
public Hero get() {
return new Hero();
}
};
System.out.println(supplier1.get());
Supplier<Hero> supplier2 = Hero::new;
System.out.println(supplier2.get());
}
@Test
public void test2() {
Function<Integer, Hero> function1 = new Function<Integer, Hero>() {
@Override
public Hero apply(Integer integer) {
return new Hero(integer);
}
};
System.out.println(function1.apply(12));
Function<Integer, Hero> function2 = Hero::new;
System.out.println(function2.apply(22));
}
@Test
public void test3() {
BiFunction<Integer, String, Hero> biFunction1 = new BiFunction<Integer, String, Hero>() {
@Override
public Hero apply(Integer integer, String s) {
return new Hero(s, integer);
}
};
System.out.println(biFunction1.apply(55, "老板"));
BiFunction<String, Integer, Hero> biFunction2 = Hero::new;
System.out.println(biFunction2.apply("Tony", 17));
}
@Test
public void test4() {
Function<Integer, Hero[]> function1 = new Function<Integer, Hero[]>() {
@Override
public Hero[] apply(Integer integer) {
return new Hero[integer];
}
};
System.out.println(function1.apply(11).length);
Function<Integer, Hero[]> function2 = Hero[]::new;
System.out.println(function2.apply(12).length);
}
}
函数式接口 | 函数描述符 |
---|---|
Predicate | T->boolean |
Consumer | T->void |
Function |
T->R |
Supplier | ()->T |
UnaryOperator | T->T |
BinaryOperator | (T,T)->T |
BiPredicate |
(L,R)->boolean |
BiConsumer |
(T,U)->void |
BiFunction |
(T,U)->R |
package com.atguigu.newfeatures;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class StreamAPITest {
@Test
//创建方式一 集合
public void test1() {
List<Employee> list = EmployeeData.getEmployees();
//顺序流
Stream<Employee> stream1 = list.stream();
//并行流
Stream<Employee> stream2 = list.parallelStream();
}
@Test
//创建方式二 数组
public void test2() {
Integer[] arr = new Integer[]{1,2,3,4,5};
Stream<Integer> stream = Arrays.stream(arr);
int[] intArr = new int[]{1,2,3,4};
IntStream intStream = Arrays.stream(intArr);
}
@Test
//创建方式三 of()
public void test3() {
Stream<String> stream = Stream.of("aa", "bb", "cc");
}
@Test
public void test4() {
//查询薪水大于7000的员工 过滤
List<Employee> list = EmployeeData.getEmployees();
Stream<Employee> stream = list.stream();
stream.filter(e -> e.getSal() > 7000).forEach(System.out::println);
System.out.println();
//截断
list.stream().limit(4).forEach(System.out::println);
System.out.println();
//跳过
list.stream().skip(5).forEach(System.out::println);
System.out.println();
//去重 (注意要重写hashCode和equals方法)
list.add(new Employee(1007, "任正非", 24, 4333.38));
list.add(new Employee(1007, "任正非", 24, 4333.38));
list.stream().distinct().forEach(System.out::println);
}
//映射map
@Test
public void test5() {
//转换为大写
List<String> list = Arrays.asList("aa","bb","cc","dd");
list.stream().map(s -> s.toUpperCase()).forEach(System.out::println);
list.stream().map(String::toUpperCase).forEach(System.out::println);
//获取员工姓名大于3的员工的姓名
List<Employee> employees = EmployeeData.getEmployees();
employees.stream().filter(e -> e.getName().length() > 3).map(e -> e.getName()).forEach(System.out::println);
employees.stream().map(e -> e.getName()).filter(name -> name.length() > 3).forEach(System.out::println);
employees.stream().map(Employee::getName).filter(name -> name.length() > 3).forEach(System.out::println);
}
//排序sorted
@Test
public void test6() {
Integer[] arr1 = new Integer[]{12,33,374,293};
Arrays.stream(arr1).sorted().forEach(System.out::println);
String[] arr2 = new String[]{"GG","JJ","MM","BB","NN"};
Arrays.stream(arr2).sorted((s1,s2)->s1.compareTo(s2)).forEach(System.out::println);
System.out.println();
Arrays.stream(arr2).sorted(String::compareTo).forEach(System.out::println);
}
//匹配与查找
@Test
public void test7() {
List<Employee> list = EmployeeData.getEmployees();
//年龄是否都大于18
System.out.println(list.stream().allMatch(e -> e.getAge() > 18));
//是否存在年龄大于18岁的
System.out.println(list.stream().anyMatch(e -> e.getAge() > 18));
//返回第一个对象
System.out.println(list.stream().findFirst());
//返回元素个数
System.out.println(list.stream().count());
//返回最高工资员工
System.out.println(list.stream().max((e1, e2) -> Double.compare(e1.getSal(), e2.getSal())).get().getSal());
//返回最低工资员工
System.out.println(list.stream().map(Employee::getSal).min((sal1, sal2) -> Double.compare(sal1, sal2)).get());
System.out.println(list.stream().map(Employee::getSal).min(Double::compare).get());
//遍历list
list.forEach(System.out::println);
}
//归约
@Test
public void test8() {
//计算1-10自然数之和
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
System.out.println(list.stream().reduce(0, (x1, x2) -> x1 + x2));
System.out.println(list.stream().reduce(10, (x1, x2) -> x1 + x2));
//计算员工工资总和
List<Employee> employeeList = EmployeeData.getEmployees();
System.out.println(employeeList.stream().map(e -> e.getSal()).reduce(Double::sum));
}
//收集
@Test
public void test9() {
List<Employee> list = EmployeeData.getEmployees();
List<Employee> employeeList = list.stream().filter(e -> e.getSal() > 5000).collect(Collectors.toList());
employeeList.forEach(System.out::println);
}
}
static Optional ofNullable(T value)
示例:
package com.atguigu.newfeatures;
import org.junit.Test;
import java.util.Optional;
public class OptionalTest {
@Test
public void test1() {
String star = "迪丽热巴";
// star = null;
Optional<String> optional = Optional.ofNullable(star);
System.out.println(optional.get());
String finalstar = "杨幂";
String s = optional.orElse(finalstar);
System.out.println(s.toString());
}
}
Java拥有了像Python和Scala语言的REPL工具(交互式编程环境):jShell
。
可在命令行里直接声明变量,计算表达式,执行语句。无需使用main这句“废话”。
try的前面可以定义流对象,try后面的()中可以直接引用流对象的名称。在try代码执行完毕后,流对象也可以释放掉,也不用写finally了。
格式:
A a = new A();
B b = new B();
try(a;b) {
异常代码
} catch(异常类名 变量名) {
异常处理逻辑
}
不能使用的情况:
示例:
var list = new ArrayList<>();
传统switch声明语句的弊端:
示例:
package com.atguigu.newfeatures;
import org.junit.Test;
public class SwitchTest {
//->操作符
@Test
public void test1() {
int n = 1;
switch (n) {
case 1 -> System.out.println(1);
case 2,3,4 -> System.out.println(2);
default -> throw new RuntimeException("num" + n);
}
int m = 3;
int res = switch (m) {
case 1 -> 1;
case 2,3,4 -> 2;
default -> throw new RuntimeException("num" + m);
};
System.out.println(res);
}
//yield相当于return
//与return的区别是return退出整个switch 而yield仅仅退出case
@Test
public void test2() {
int m = 3;
int res = switch (m) {
case 1 -> {
yield 1;
}
case 2,3,4 -> {
yield 2;
}
default -> throw new RuntimeException("num" + m);
};
System.out.println(res);
}
}
模式匹配:
之前版本:
static String formatter(Object o) {
String formatted = "unknown";
if (o instanceof Integer i) {
formatted = "int " + i;
} else if (o instanceof Long l) {
formatted = "long " + l;
}
return formatted;
}
JDK17:
static String formatterSwitch(Object o) {
String formatted = switch(o) {
case Integer i:
yield "int" + i;
case Long l:
yield "long" + l;
}
return formatted;
}
示例:
package com.atguigu.newfeatures;
import org.junit.Test;
public class BlockTest {
@Test
public void test1() {
String s0 = " +
" title=\"成功提示的文案\"\n" +
" type=\"success\">\n" +
" ";
System.out.println(s0);
String s1 = """
""";
System.out.println(s1);
String s2 = """
<el-alert \
title="成功提示的文案" \
type="success">
\s</el-alert>
""";
System.out.println(s2);
}
}
JDK14前,遇见一个女生,先谈恋爱再…
JDK14后,遇见一个女生,孩子名字都想好了
示例:
if(obj instanceof String) {
String str = (String) obj;
...
}
等于以下代码:
if (obj instanceof String str) {
...
}
定义一个类:
package com.atguigu.newfeatures;
import java.util.Objects;
public class Order {
public int id;
public String name;
public Order(int id, String name) {
this.id = id;
this.name = name;
}
public int id() {
return id;
}
public String name() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Order order = (Order) o;
return id == order.id && Objects.equals(name, order.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
@Override
public String toString() {
return "Order{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
等价于:
package com.atguigu.newfeatures;
public record Order1(int id, String name) {
}
示例:
package com.atguigu.newfeatures;
import org.junit.Test;
import java.util.HashSet;
public class OrderTest {
@Test
public void test1() {
Order order1 = new Order(1,"马云");
System.out.println(order1);
System.out.println(order1.id());
System.out.println(order1.name());
Order order2 = new Order(1,"马云");
System.out.println(order1.equals(order2));
HashSet<Order> set = new HashSet<>();
set.add(order1);
set.add(order2);
System.out.println(set);
}
@Test
public void test2() {
Order1 order1 = new Order1(1,"马云");
System.out.println(order1);
System.out.println(order1.id());
System.out.println(order1.name());
Order1 order2 = new Order1(1,"马云");
System.out.println(order1.equals(order2));
HashSet<Order1> set = new HashSet<>();
set.add(order1);
set.add(order2);
System.out.println(set);
}
}
注意:
record声明的类中可以定义静态字段、静态方法、构造器或实例方法,例如:
static String info = "you are a man";
public static void show() {
System.out.println("我是人");
}
public Person() {
this(0, null);
}
public void eat() {
System.out.println("人吃饭");
}
不能在record声明的类中定义实例字段,类不能声明为abstract,不能声明显式父类等
final int age;
abstract record Dog(int id){}
record Cat(int id) extends Thread{}
示例:
package com.atguigu.newfeatures;
//密封类只能被指定的类继承
public sealed class Person permits A, B, C{
}
//指定的子类必须是final sealed non-sealed 之一
final class A extends Person {}
sealed class B extends Person permits D{}
non-sealed class D extends B{}
non-sealed class C extends Person{}