你所不知道的Lambda表达式和常用的函数式接口
你所不知道的Lambda表达式和常用的函数式接口

推荐答案
同学,您好!你所不知道的Lambda表达式和常用的函数式接口
一. 什么是Lambda表达式
Lambda表达式是JDK1.8中新增的一种方式,用于替代匿名内部类,该表达式可以让开发人员更加关注于具体需要传递的方法,而不是因为需要传递一个方法而创建一个对象。
二. Lambda表达式
1. 基本语法
Lambda省去?向对象的条条框框,格式由3个部分组成:
参数部分
箭头
代码块
比如:(参数类型 参数名称) -> { 代码语句 }
2. 格式说明
?括号内的语法与传统?法参数列表?致:?参数则留空;多个参数则?逗号分隔;
-> 是新引?的语法格式,代表指向动作;
?括号内的语法与传统?法体要求基本?致。
3. Lambda的省略格式
所谓的Lambda表达式的省略原则是:可推导即可省略。
Lambda强调的是“做什么”?不是“怎么做”,所以凡是可以根据上下?推导得知的信息,都可以省略。
3.1 省略规则
在Lambda标准格式的基础上,使?省略写法的规则为:
?括号内参数的类型可以省略;
如果?括号内有且仅有?个参,则?括号可以省略;
如果?括号内有且仅有?个语句,则?论是否有返回值,都可以省略?括号、return关键字及语句、分号。
4. Lambda的使用前提
Lambda的语法?常简洁,完全没有?向对象复杂的束缚,但是使?时有?个问题需要特别注意:
使?Lambda必须具有接?,且要求接?中有且仅有?个抽象?法。 ?论是JDK内置的
Runnable 、 Comparator 接?还是?定义的接?,只有当接?中的抽象?法存在且唯?时,才可以使用Lambda
2. 使?Lambda必须具有上下?推断。 也就是?法的参数或局部变量类型必须为Lambda对应的接?
类型,才能使?Lambda作为该接?的实例。
5. 常用函数式接口
JDK提供了?量常?的函数式接?以丰富Lambda的典型使?场景,它们主要在 java.util.function
包中被提供. 常用的函数式接口包括以下四个。
5.1 Supplier接?
java.util.function.Supplier 接?仅包含?个?参的?法: T get() 。?来获取?个泛型参数,可以指定类型的对象数据。由于这是?个函数式接?,这也就意味着对应的Lambda表达式需要“对外提供”?个符合泛型类型的对象数据。
5.1.1 基本使用方式如下:
public class SupplierDemo {
// 为了获取一个int类型的数据
private static int getNum(Supplier supplier) {
// get方法 -- 返回一个指定数据类型 T 的数据
return supplier.get();
}
public static void main(String[] args) {
// int num = getNum(new Supplier() {
// @Override
// public Integer get() {
// return 50;
// }
// });
System.out.println(getNum(() -> 50));
// 1. 获取30 60 两个数字中的最大值
// getNum(new Supplier() {
// @Override
// public Integer get() {
// return Math.max(30, 60);
// }
// });
getNum(()->Math.max(30, 60));
// 有一个数组
int[] nums = {1,5,4,8,4,51,2,1,6,8};
// 通过getNum方法获取数组的最大值
// getNum(new Supplier() {
// @Override
// public Integer get() {
// Arrays.sort(nums);
// return nums[nums.length - 1];
// }
// });
int num = getNum(() -> {
Arrays.sort(nums);
return nums[nums.length - 1];
});
System.out.println(num);
}
}
5.2 Consumer接?
java.util.function.Consumer 接?则正好与Supplier接?相反,它不是?产?个数据,?是消费?个数据,其数据类型由泛型决定。
Consumer 接?中包含抽象?法 void accept(T t) ,意思是说消费?个执?泛型的数据
Consumer 接?中包含默认?法:andThen
如果?个?法的参数和返回值全都是 Consumer 类型,那么就可以实现效果:消费数据的时候,?先做?个操作, 然后再做另?个操作,实现组合。?这个?法就是 Consumer 接?中的default?法 andThen
5.2.1 下?是JDK的源代码:
default Consumer andThen(Consumer after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
基本使用方式如下:
public class ConsumerDemo {
// 使用一个指定的String类型的数据
private static void useString(Consumer consumer, String string){
consumer.accept(string);
}
private static void useString(Consumer consumer, Supplier supplier) {
consumer.accept(supplier.get());
}
// 返回的Consumer对象的目的 -- 使用accept方法接收参数,传递给first和second使用
private static Consumer andThen(Consumer first, Consumer second){
return new Consumer() {
@Override
public void accept(String s) {
first.accept(s);
second.accept(s);
}
};
}
private static void andThenTest(Consumer first, Consumer second, String string){
// Consumer then = first.andThen(second);
// then.accept(string);
// 前后两个接口对象之间,没有数据上的联系
// 两个接口 分别处理的都是原本的数据
first.andThen(second).accept(string);
System.out.println("---------");
Consumer consumer = andThen(first, second);
consumer.accept(string);
}
public static void main(String[] args) {
// useString(new Consumer() {
// @Override
// public void accept(String s) {
// System.out.println(s.length());
// }
// }, "lambda");
// useString((String s)->{
// System.out.println(s.length());
// }, "lambda");
useString(s->System.out.println(s.length()), "lambda");
// useString(s-> System.out.println(s), "lambda");
// useString(System.out::println, "lambda");
useString(s-> {
System.out.println(s.concat(Integer.valueOf(s.length()).toString()));
System.out.println(s + s.length());
}, "lambda");
useString(s->{
System.out.println(s.length());
},()->{
return "123456oiuytr";
});
andThenTest(s -> System.out.println(s.toUpperCase()),
s->System.out.println(s.substring(0, 3)), "lambda Exp");
}
}
5.3 Predicate接?
有时候我们需要对某种类型的数据进?判断,从?得到?个boolean值结果。这时可以使
?java.util.function.Predicate接?。
Predicate 接?中包含?个抽象?法: boolean test(T t)
该接口也存在三个默认的方法,分别是and 、 or 和negate, 分别表示与 、或 、非三种逻辑处理。
5.3.1 接口代码示例:
public class PredicateDemo {
private static boolean testMethod(Predicate predicate, String s){
// test方法返回一个boolean类型的数据
return predicate.test(s);
}
private static boolean andMethod(Predicate first, Predicate second, String s){
return first.and(second).test(s);
}
private static boolean orMethod(Predicate first, Predicate second, String s) {
return first.or(second).test(s);
}
private static boolean negateMethod(Predicate predicate, String s) {
return predicate.negate().test(s);
}
public static void main(String[] args) {
// 1. 判断一个字符串是否是由txt结尾的
// boolean result = testMethod(new Predicate() {
// @Override
// public boolean test(String s) {
// return s.endsWith("txt");
// }
// }, "newFile");
// boolean result = testMethod((String s)->{
// return s.endsWith("txt");
// }, "newFile");
boolean result = testMethod(s->s.endsWith("txt"), "newFile");
System.out.println(result);
boolean r1 = andMethod(s -> s.length() > 6,
s -> s.startsWith("a"), "asijhgvbnm");
boolean r2 = orMethod(s -> s.length() > 6,
s -> s.equals("abcd"), "asdfghjkl");
boolean r3 = negateMethod(s -> s.endsWith("a"), "asdfghjkl");
System.out.println(r1 + " - " + r2 + " - " + r3);
}
}
5.4 Function接?
java.util.function.Function接??来根据?个类型的数据得到另?个类型的数据,前者称为前置条件,后者称为后置条件。
Function 接?中最主要的抽象?法是: R apply(T t) ,根据类型T的参数获取类型R的结果。
Function接?中有?个默认的andThen?法,?来进?组合操作。
5.4.1 基本使用方式如下
public class FunctionDemo {
private static void applyMethod(Function function, String s){
Integer apply = function.apply(s);
System.out.println("从字符串" + s + "中获取的integer类型数据是:" + apply);
}
private static Function andThen(Function first, Function second){
// T = String; R = Integer; V=Boolean
// String --> Boolean
return new Function() {
@Override
public Boolean apply(String s) {
// String --> Integer
Integer apply = first.apply(s);
// Integer --> Boolean
Boolean apply1 = second.apply(apply);
return apply1;
}
};
}
private static void andThenMethod(Function first, Function second, String s){
Function then = first.andThen(second);
// 因为andThen方法在实现的时候 前面一个的结果给后面一个处理
// 前者T R --> 后者 R V ==> T --> V
Boolean apply = then.apply(s);
System.out.println(apply);
System.out.println("------");
Function function = andThen(first, second);
Boolean b = function.apply(s);
System.out.println(b);
}
public static void main(String[] args) {
// applyMethod(new Function() {
// @Override
// public Integer apply(String s) {
// return s.indexOf("a");
// }
// }, "fashjkl");
// applyMethod((String s)->{
// return s.indexOf("a");
// }, "fashjkl");
applyMethod(s->s.indexOf("a"), "fashjkl");
andThenMethod(s-> s.length(),
i -> i > 20, "sadfghjkl;");
// andThenMethod(String::length,
// i -> i > 20, "sadfghjkl;");
}
}
现在你学会Lambda表达式怎么用了吗?

热议问题






