目录
- Lambda 表达式:Lambda 表达式是 JDK 8 中最引人注目的特性之一。它们提供了一种简洁、函数式的语法,用于表示匿名函数。Lambda 表达式在集合操作、事件处理和并发编程等方面非常有用。
- Stream API:Stream API 是一种处理集合数据的新方式。它提供了一种流式处理的方式,可以方便地进行过滤、映射、归约等操作。Stream API 可以极大地简化集合操作的代码,并且可以有效地支持并行处理。
- 接口的默认方法:JDK 8 允许接口中定义默认方法(default methods)。默认方法是指在接口中提供一个默认的方法实现,可以直接在实现接口的类中使用或者重写。这使得在接口的演化过程中更容易向后兼容。
- 方法引用:方法引用允许直接通过方法的名字来引用已经存在的方法。它可以使代码更简洁、易读,并且提供了对方法的复用。
- 函数式接口:JDK 8 引入了函数式接口的概念。函数式接口是指只包含一个抽象方法的接口,它们可以被 Lambda 表达式所使用。函数式接口为函数式编程提供了基础。
- 日期/时间 API:JDK 8 引入了新的日期和时间 API,用于替代旧的 Date 和 Calendar 类。新的日期/时间 API 提供了更好的设计和易用性,并且提供了对日期和时间的各种操作和计算。
- CompletableFuture:CompletableFuture 是一种支持异步编程的新的工具类。它提供了方便的方法来处理异步任务的结果,包括异步任务的组合和串行化。
- 并发增强:JDK 8 在并发编程方面进行了一些增强。它引入了新的原子类、并发集合和并发工具,以简化并发编程的开发和管理。
1、Lambda表达式
1.1 lambda表达式的语法
(参数列表)->{}
():参数列表
->:连接符 连接的是参数以及方法体。
{}: 方法体。
1.2 无参无返回值的Lambda
public class Test02 {
public static void main(String[] args) {
//匿名内部类的方式
UserService userService=new UserService() {
@Override
public void show() {
System.out.println("这是匿名内部类的show方法的实现");
}
};
fun(userService);
//使用lambda表达式--该接口必须为函数式接口
fun(()->{
System.out.println("这是lambda表达的show方法");
});
}
public static void fun(UserService userService){
userService.show();
}
}
//函数式接口:里面有且仅有一个抽象方法。 ---只有这种接口才能使用lambda表达式
interface UserService{
public void show();
}
1.3 有参有返回值
public class Test03 {
public static void main(String[] args) {
//创建一个ArrayList集合,其中存放了"Person"对象
ArrayList<Person> list = new ArrayList<>();
//向集合中添加元素-人物姓名和年龄
list.add(new Person("张三", 19));
list.add(new Person("李四", 8));
list.add(new Person("王五", 20));
list.add(new Person("赵六", 17));
//按年龄从小到大排序
System.out.println(list);
//使用集合工具类"Collections"- 匿名内部类
/*Collections.sort(list, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge()-o2.getAge();
}
});*/
//使用Lambda表达式
Collections.sort(list, (o1, o2) -> {
//这就是对函数式接口中抽象方法的简写
return o1.getAge() - o2.getAge();
});
//输出按年龄从小到大排序的结果
System.out.println(list);
}
}
class Person {
private String name;
private Integer age;
public Person() {
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
/**
* 获取
*
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
*
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
*
* @return age
*/
public Integer getAge() {
return age;
}
/**
* 设置
*
* @param age
*/
public void setAge(Integer age) {
this.age = age;
}
public String toString() {
return "Person{name = " + name + ", age = " + age + "}";
}
}
1.4 Lambda表达式的省略写法
在lambda表达式的标准写法基础上,可以使用省略写法的规则为:
小括号内的参数类型可以省略[]
如果小括号内有且仅有一个参数,则小括号可以省略
如果大括号内有且仅有一个语句,可以同时省略大括号,return 关键字及语句分号。
public class Test04 {
public static void main(String[] args) {
fun((str)->
str.toUpperCase()
);
}
public static void fun(USB usb){
String s = usb.toUpper("hello");
System.out.println(s);
}
}
interface USB{
public String toUpper(String str);
}
1.5 Lambda表达式使用的前提
Lambda表达式的语法是非常简洁的,但是Lambda表达式不是随便使用的,使用时有几个条件要特别注意
-
方法的参数或局部变量类型必须为接口才能使用Lambda
-
接口中有且仅有一个抽象方法(@FunctionalInterface)
后面我们使用lambda表达式主要核心使用再Stream流中。
2、内置函数式接口
要想使用lambda表达式它的前提就是必须是函数式接口。
2.1 内置函数式接口的由来
public class Test {
public static void main(String[] args) {
fun(arr->{
int sum = 0;
for (int i : arr) {
sum+=i;
}
return sum;
});
}
public static void fun(Operation operation){
int[] arr = {1,2,3,4,5};
int sum = operation.getSum(arr);
System.out.println("数组的和:"+sum);
}
}
@FunctionalInterface
interface Operation{
public int getSum(int[] arr);
}
分析:
我们知道使用Lambda表达式的前提是需要有函数式接口,而Lambda表达式使用时不关心接口名,抽象方法名。只关心抽象方法的参数列表和返回值类型。因此为了让我们使用Lambda表达式更加的方便,在JDK中提供了大量常用的函数式接口. 大多数无需自己再定义函数式接口,而可以直接使用jdk内置的函数式接口。分成四类。
2.2 消费性函数式接口Consumer
适合有参数,但是没有返回值的。
public class Test {
public static void main(String[] args) {
/*Consumer<Double> consumer = t->{
System.out.println("今天坐车花费了" + t + "元");
};*/
fun(t->{
System.out.println("今天坐车花费了" + t + "元");
},200.00);
}
public static void fun(Consumer<Double> consumer,Double money){
consumer.accept(money);
}
}
2.3 供给型函数式接口---Supplier
无参,需要返回值的接口类。
public class Test01 {
public static void main(String[] args) {
fun(()->{
return new Random().nextInt(10);
});
}
public static void fun(Supplier<Integer> supplier){
Integer i = supplier.get();
System.out.println("结果:" + i);
}
}
2.3 函数型函数式接口---Function<T,R>
T: 参数的泛型
R:返回值的泛型。
public class Test01 {
public static void main(String[] args) {
fun2(t->t.toUpperCase(),"hello world");
}
public static void fun2(Function<String,String> function,String str){
String apply = function.apply(str);
System.out.println("结果:" + apply);
}
}
2.4 断言型函数式接口--Predicate
T: 参数
boolean:返回值类型。
public class Test01 {
public static void main(String[] args) {
//Predicate断言型
fun3(t->t>=18,18);
}
public static void fun3(Predicate<Integer> predicate,Integer age){
boolean test = predicate.test(age);
System.out.println("是否成年:"+test);
}
}