1 lambda表达式:实现接口,并创建对象,可以理解为是匿名内部类的简化写法
说明:参数类型可以省略,如果是单参函数,括号也可以省略
语法:
①(参数表)->{方法实现}
②(参数表)-> 表达式 注:等价于return表达式
③ (参数表) -> 单句实现 注:return语句不能视为单句实现,对于无返回值的单句实现,{}也可以不写
基本使用样例
public class A {
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("aa",18));
list.add(new Student("bb",19));
list.add(new Student("cc",20));
//匿名内部类实现
Filter filter = new Filter() {
@Override
public boolean test(Student s) {
return s.getAge() > 18;
}
};
//lambda实现
Filter f1 = t -> t.getAge()>18;
List<Student> students = filterTest(list, filter);
students.forEach(System.out::println);
}
private static List<Student> filterTest(List<Student> list, Filter filter){
ArrayList<Student> students = new ArrayList<>();
list.forEach(s->{
if(filter.test(s)) students.add(s);
});
return students;
}
}
interface Filter{
boolean test(Student s);
}
class Student{
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
1.1 函数式接口: 凡是只有一个方法的接口称为函数式接口
对于自定义接口,可以使用@FunctionalInterface注解来进行标注验证,如下图
@FunctionalInterface
interface Filter{
boolean test(Student s);
}
我们常见的函数式接口,函数描述符左侧为入参,右侧为出参。
接口 | 函数描述符 | 方法名 | 备注说明 |
---|---|---|---|
Predicate《T》 | T-> boolean | test | |
Conumer《T》 | T- > void | accept | |
Function《T,R》 | T->R | apply | |
Suppliier《T》 | ()->T | get | 功能与call()相似 |
Bipredicate《T,R》 | (T,R)-> boolean | test | |
BiConsumer《T,R》 | (T,R) ->void | accept | 如在遍历map时可用到 |
BiFunction《T,U,R》 | (T,U)->R | apply | |
UnaryOperator《T》 | T>T | apply | 给的类型和返回值类型相同,是特殊的Function |
BinaryOperator《T》 | (T,T) -> T | apply | 给的类型和返回值类型相同,是特殊的Function |
常见接口使用案例
① predicate
//匿名内部类实现
Predicate<Student> predicate = new Predicate<Student>() {
@Override
public boolean test(Student student) {
return student.getAge() > 18;
}
};
//lambda形式
Predicate<Student> pred = t->t.getAge() > 18;
② Consumer
Consumer<Student> consumer = new Consumer<Student>() {
@Override
public void accept(Student student) {
System.out.println(student);
}
};
Consumer<Student> consume = t-> System.out.println(t);
③ Function
public static void main(String[] args) {
List<String> list = Arrays.asList("AAAA", "BBBB");
//匿名内部类实现
Function<String, String> function = new Function<String, String>() {
@Override
public String apply(String s) {
return s.toLowerCase();
}
};
//lambda实现
Function<String, String> functio = s->s.toLowerCase();
List<String> strings = filterTest(list, functio);
strings.forEach(System.out::println);
}
private static List<String> filterTest(List<String> list,Function<String, String> function){
ArrayList<String> students = new ArrayList<>();
list.forEach(s->{
students.add(function.apply(s));
});
return students;
}
④ Supplier
Supplier<String> supplier = new Supplier<String>() {
@Override
public String get() {
return "aaaa";
}
};
Supplier<String> supplie = () -> "aaaaa";
System.out.println("AAA"+ supplier.get());
1.2 方法引用: 是lambda的特殊写法,从代码上更直观,最真实的还原程序员真实意图
常见的方法如下:
类型 | lambda | 方法引用 |
---|---|---|
参数方法 | (A arg0, B rest)-> arg0.method(rest) | A::method |
参数方法 | (A a)-> a.method() | A::method |
静态方法 | (args)-> ClassName.method(args) | ClassName::method |
其他对象方法 | (args)-> expr.method(args) | expr::method |
构造方法 | ()-> new Student | Student::new |
构造方法 | (String s)-> new Student(s) | Student::new |
样例一:方法引用
public class Test {
public static void main(String[] args) {
I1 i1 = new I1() {
@Override
public void test(A a) {
a.method();
}
};
I1 test01 = (A a) -> a.method();
I1 test02 = A::method;
I2 i2 = new I2() {
@Override
public void test(A a, String b) {
a.method(b);
}
};
I2 test03 = (A a,String b) -> a.method(b);
I3 test04 = A::method;
I3 i3 = new I3() {
@Override
public void test(A a, String b, String c) {
a.method(b, c);
}
};
I3 test05 = (A a, String b, String c) -> a.method(b,c);
I3 test06 = A::method;
I5 i5 = new I5() {
@Override
public void test(String s) {
Integer.parseInt(s);
}
};
I5 test07 = s -> Integer.parseInt(s);
I5 test08 = Integer::parseInt;
}
}
class A {
public void method(){
}
public void method(String a){
}
public void method(String a ,String b){
}
}
interface I1{
void test(A a);
}
interface I2{
void test(A a ,String b);
}
interface I3{
void test(A a ,String b, String c);
}
interface I4{
void test(String s ,A a);
}
interface I5{
void test(String s);
}
案例二:构造方法
public class Test {
public static void main(String[] args) {
Q q = new Q() {
@Override
public Student method() {
return new Student();
}
};
Q test01 = () -> new Student();
Q test02 = Student::new;
W w = new W() {
@Override
public Student method(String s) {
return new Student(s);
}
};
W test03 = s ->new Student(s);
W test04 = Student::new;
Supplier<Student> supplier = Student::new;
Function<String,Student> function = Student::new;
}
}
interface Q{
Student method();
}
interface W{
Student method(String s);
}
class Student{
public Student() {
System.out.println("A");
}
public Student(String a) {
System.out.println("B");
}
public Student(String a,String b) {
System.out.println("c");
}
}
案例三:比较器
public class Test {
public static void main(String[] args) {
ArrayList<Employee> list = new ArrayList<>();
list.add(new Employee("aa",11,100.0));
list.add(new Employee("cc",33,300.0));
list.add(new Employee("bb",22,200.0));
Comparator<Employee> comparator = Comparator.comparingInt(new ToIntFunction<Employee>() {
@Override
public int applyAsInt(Employee value) {
return value.getAge();
}
});
Comparator<Employee> comparator1 = Comparator.comparingInt(value -> value.getAge());
Comparator<Employee> comparator2 = Comparator.comparingInt(Employee::getAge);
Comparator<Employee> comparator3 = Comparator.comparing(Employee::getName);
Comparator<Employee> comparator4 = Comparator.comparingDouble(Employee::getSalary);
//两个条件的比较
Comparator<Employee> comparator5 = comparator3.thenComparing(comparator4);
list.sort(comparator4.reversed());
list.forEach(System.out::println);
}
}
class Employee{
String name;
int age;
double salary;
public Employee() {
}
public Employee(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
'}';
}
}
1.3 Optional: 针对的是空指针异常的,可避免空指针异常
一、创建Optional
①创建空值:empty()
Optional<Object> empty = Optional.empty();
②创建非空值:of(T value)
Optional<String> optional = Optional.of("AAA");
③创建Optional对象,允许null值:ofNullable(T value)
Optional<Object> optionalO = Optional.ofNullable(new Employee());
二、访问Optional
①判断值是否存在:isPresent()
Optional<String> optional = Optional.of("AAA");
System.out.println(optional.isPresent());
②获取值,空值抛异常:get()
System.out.println(optional.get());
③获取值,如果无值则取默认值:orElse(T value)
Optional<Object> empty = Optional.empty();
System.out.println(empty.orElse("BBB"));
④如果值存在,则消费值,值不存在,不抛空指针异常:ifPresent(Consumer consumer)
optional.ifPresent(System.out::print);
使用样例:
传统方式:会抛空指针异常,如为了避免空指针异常,需要进行频繁的if判断
public class Test {
public static void main(String[] args) {
Man man = new Man();
String name = man.woman.name;
System.out.println(name);
}
}
class Man{
String name;
Woman woman;
}
class Woman{
String name;
public void method(){
}
}
Optional:不会抛空指针异常,避免了频繁的if判断
public class Test {
public static void main(String[] args) {
Man man = new Man();
Optional<Woman> woman = man.wife;
String name = woman.get().name;
System.out.println(name);
}
}
class Man{
String name;
Optional<Woman> wife = Optional.ofNullable(new Woman());
public Optional<Woman> getWife(){
return wife;
}
}
class Woman{
String name;
public void method(){
}
}