一些相关的新特性总结
JDK8
Lambda表达式⭐
编程思想
面向对象编程思想: 强调的是找对象,帮我们做事(通过对象完成)
函数式编程思想: 强调的是结果,不强调过程(不需要对象就可以完成)
定义
是什么
Lambda表达式是一种匿名函数。它可以作为参数传递给方法或函数,并且可以在需要函数对象的地方使用。(是可以传递的代码,一个接口中待重写的抽象方法)
Lambda表达式可以简化代码,使代码更加简洁和易读。
出现:JDK8
语法格式
例子:
public class Demo01Lambda {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("我执行了");
}
}).start();
System.out.println("============");
new Thread(()-> System.out.println("我执行了")).start();
ArrayList<String> list = new ArrayList<>();
}
}
作用
作为参数,传递重写的方法,简化函数式接口的匿名内部类写法。
使用前提
必须是函数式接口做方法参数传递(传递的参数是函数式接口)
函数式接口:有且只有一个抽象方法的接口,用@FunctionalInterface去检测
@FunctionalInterface
public interface USB {
void open();
}
省略规则
可以省略的内容
- 重写方法的参数类型
- 如果重写方法只有一个参数,所在的小括号
- 如果方法体中只有一句话,那么所在的大括号以及分号
- 如果方法体中只有一句话并且带return的,那么所在的大括号,分号以及return
例子:重写Comparator接口中的compare方法(可以直接传递它要进行重写的方法)
public class Person {
private String name;
private Integer age;
public Person() {
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Demo03Lambda {
public static void main(String[] args) {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("张三",10));
list.add(new Person("李四",8));
list.add(new Person("王五",9));
/* Collections.sort(list, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge()-o2.getAge();
}
});
*/
System.out.println("=============Lambda==========");
/* Collections.sort(list,(Person o1, Person o2)-> {
return o1.getAge()-o2.getAge();
});*/
System.out.println("===========Lambda表达式简化形式==========");
Collections.sort(list,(o1, o2)-> o1.getAge()-o2.getAge());
System.out.println(list);
}
}
书写技巧
在不熟悉时,需要书写出匿名内部类,在根据匿名内部类改写。这时体现得较为繁琐。
在熟悉常见的函数式接口后,可以直接写出最终的简化形式的Lambda表达式
Collections.sort(list, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge()-o2.getAge();
}
});
新手期,在不熟练时的书写方法
1.去除匿名内部类的类名及外层括号
Collections.sort(list,
public int compare(Person o1, Person o2) {
return o1.getAge()-o2.getAge();
}
);
2.去除方法名及修饰符,在参数列表与括号间+箭头
Collections.sort(list,
(Person o1, Person o2) -> {
return o1.getAge()-o2.getAge();
}
);
3.根据规则简化
Collections.sort(list,(o1, o2)-> o1.getAge()-o2.getAge());
函数式接口
定义
有且只有一个抽象方法的接口, @FunctionalInterface检测
例子
@FunctionalInterface
public interface USB {
void open(String s);
//void close();
}
package com.hsc.base04.lambda_demo;
public class Test01 {
public static void main(String[] args) {
//匿名内部类传递方法
method(new USB() {
@Override
public void open(String s) {
System.out.println(s+"开启了");
}
});
//Lambda传递方法
System.out.println("=====Lambda====");
method((String s)->{
System.out.println(s+"开启了");
});
//Lambda简化传递方法
System.out.println("=====Lambda简化版====");
method(s-> System.out.println(s+"开启了"));
}
//需要传递一个函数式接口,其方法的运行依赖于该接口的实现
public static void method(USB usb){
usb.open("鼠标");
}
}
常见的函数式接口
函数式接口单独使用会很繁琐,需要结合Stream流使用
1.Supplier(供给)
-
Supplier:代表一个供应商,它提供一个T类型的结果。没有参数,返回一个结果。
T get();
-
使用场景:
- 需要延迟计算,或者需要每次调用时都生成一个新的结果的情况下。
-
例子:
2.Consumer(消费)
- Consumer:代表一个消费者,它接受一个T类型的输入,但没有返回值。
void accept(T t); - 使用场景
- 可以用于遍历集合并对每个元素执行操作。
- 例子
3.Function(函数)
- Function<T, R>:代表一个函数,它接受一个T类型的输入并返回一个R类型的结果。
R apply(T t); - 使用场景
- 可以用于将一种类型的对象转换为另一种类型,或者执行一些计算并返回结果。
- 例子
4.Predicate(判断)
- Predicate:代表一个断言,它接受一个T类型的输入并返回一个布尔值。
boolean test(T t); - 使用场景
- 可以用于过滤集合中满足特定条件的元素。
5.Runnable
- Runnable:代表一个没有参数和返回值的操作。
void run(); - 应用场景:可以将该实现传递给一个线程(Thread)对象中,并通过 start() 方法启动线程,使得 run() 方法中的操作在一个新的线程中执行。