Lambda表达式
其实Lambda并不能算作Java基础内容更应该归类为Java简化开发原则,因为懒得开新专辑了所以就一并放在Java基础知识中整理掉。 本文将按照不同Lambda语法种类进行整理。
基本概念
Lambda 表达式是 Java 在 JDK 8 中引入的一种新的语法元素和操作符(操作符为“->”,也称Lambda操作符或箭头操作符)它将 Lambda 分为两个部分:
- 左侧:小括号内 指定了 Lambda 表达式需要的 形参列表;
- 右侧:大括号内 指定了 Lambda 体,是抽象方法的实现逻辑,也是 Lambda 表达式要执行的功能。
对于形参列表:
- 空参需要提供小括号:
() -> {}
- 单个参数可以省略小括号:
e -> {}
- 参数类型可省略,编译器会进行类型推断
对于Lambda体:
- 可以包含多行代码、可以 return:
() -> {return null;};
- 单行代码可省略{}:
() -> System.out.println("Hello, World!");
- 有返回值且只返回为单行代码可以不写return和{}:
(x,y) -> Integer.compare(x,y);
//使用Lambda表达式遍历HashMap中的键值对
HashMap.forEach((k,v) -> {
System.out.println("key = " k " value = " v);
}); //注意此处的分号
//使用Lambda表达式处理线程接口
Runnable r1 = () -> System.out.println("Hello, World!");
//保留数据类型
Consumer<String> con = (String str) -> {System.out.print(str);};
//省略数据类型
Consumer<String> con = (str) -> {System.out.print(str);};
//拥有返回值
Comparator<Integer> com = (x,y) -> {
System.out.print("returned success");
return Integer.compare(x,y);
};
//拥有返回值且为返回值为单语句
Comparator<Integer> com = (x,y) -> Integer.compare(x,y);
方法引用
方法引用是函数式接口的一个实例,通过方法的名字来指向一个方法。当需要传递给Lambda体进行操作且有已经实现了的方法,就可以使用方法引用。语法如下:
代码语言:javascript复制类或对象名::方法名
包括如下3种情况:
代码语言:javascript复制对象::非静态方法
类::静态方法
类::非静态方法
- 针对第一第二种情况要求:接口中抽象方法的形参列表 和 返回值类型 与 方法引用中的形参列表 和 返回值类型 保持一致
- 针对第三种情况要求:当函数式接口方法的第一个参数是 需要引用方法 的调用者,并且第二个参数是 需要引用方法 的参数(或无参数)时,使用
ClassName::methodName
对象::new
对象::new
语法是 JDK8 以后新增的 Lambda 表达式一部分的内容,它主要用于实例化一个静态的对象模型。
public class demo {
public static void main(String[] args) {
//第一种方式
ICar iCar1 = new ICar() {
@Override
public Car getCar(String name, Integer money) {
return new Car(name, money);
}
};
System.out.println(iCar1.getCar("凯迪拉克", 30));
//第二种方式
ICar iCar2 = (name, money) -> new Car(name, money);
Car car = iCar2.getCar("凯迪拉克", 30);
System.out.println(car.toString());
//第三种方式
ICar iCar3 = Car::new;
Car car3 = iCar3.getCar("凯迪拉克", 30);
System.out.println(car3);
}
}
@FunctionalInterface
interface ICar {
Car getCar(String name, Integer money);
}
class Car{
private String name;
private Integer money;
public Car(String name, Integer money) {
this.name = name;
this.money = money;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getMoney() {
return money;
}
public void setMoney(Integer money) {
this.money = money;
}
@Override
public String toString() {
return "Car{"
"name='" name '''
", money=" money
'}';
}
}
Stream API
- Stream关注的是对数据的运算,与CPU打交道
- 集合关注的是数据的存储,与内存打交道
- 从 JDK8 开始,提供了一套API,使用这套API可以对内存中的数据进行过滤、排序、映射、归约等操作(类似于sql对数据库中表的相关操作)。
Stream流的注意点:
① Stream 自己不会存储元素。 ② Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。 ③ Stream 操作是同步执行的。这意味着他们会等到需要结果的时候才执行。
Stream流的中间操作:
- 筛选与切片
方法 | 描述 |
---|---|
filter(Predicate p) | 接受Lambda从流中排除一些元素。 |
distinct() | 筛选,通过流产生元素的hashCode()和equals()方法去除重复元素。 |
limit(long maxSize) | 截断流,使其元素数量不超过给定数量。 |
skip(long n) | 跳过元素,返回一个去除了前n个元素的新的流。若流中元素不足n个,则返回一个空的流。与截断流互补。 |
- 映射
方法 | 描述 |
---|---|
map(Function f) | 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。 |
map ToDouble(ToDoubleFunction f) | 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 DoubleStream。 |
map ToInt(ToIntFunction f) | 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 IntStream。 |
map ToLong(ToLongFunction f) | 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 LongStream。 |
flatMap(Function f) | 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个新的流。 |
- 排序
方法 | 描述 |
---|---|
sorted() | 产生一个新流,其中按自然顺序排序。 |
sorted(Comparator com) | 产生一个新流,其中按比较器顺序排序。 |
Stream流的终止操作:
- 匹配与查找
方法 | 描述 |
---|---|
allMatch(Predicate p) | 检查是否匹配所有元素 |
anyMatch(Predicate p) | 检查是否至少匹配一个元素 |
noneMatch(Predicate p) | 检查是否没有匹配所有元素 |
findFirst() | 返回第一个元素 |
findAny() | 返回当前流中的任意元素 |
- 归约
方法 | 描述 |
---|---|
count() | 返回流中元素总数 |
max(Comparator c) | 返回流中最大值 |
min(Comparator c) | 返回流中最小值 |
forEach(Comsumer c) | 内部迭代(使用Collection接口,需要用户去做迭代,称为外部迭代,而Stream API使用内部迭代) |
- 收集
方法 | 描述 |
---|---|
collect(Collector c) | 将流转换为其他形式。接收一个 Collector 接口的实现方法,用于给 Stream 中元素做汇总操作。 |
Stream流的Collectors:
方法 | 返回类型 | 作用 |
---|---|---|
toList | List<T> | 把流中的元素收集到List中 |
List<Employee> emps = list.stream().collect(Collectors.toList()); | ||
toSet | Set<T> | 把流中的元素收集到Set中 |
Set<Employee> emps = list.stream().collect(Collectors.toSet()); | ||
toCollection | Collection<T> | 把流中的元素收集到List中 |
Collection<Employee> emps = list.stream().collect(Collectors.toCollection()); |