Log.d("I","exe");
}
});
```
> 匿名内部类/监听器接口缺点在于代码很臃肿,而lambda表达式就是对其进行了简化.
```
func(()->Log.d("I","exe"));
```
> Lambda表达式并不能让你实现以前不能实现的功能
2. Lambda表达式的几种样式
-
总体样式: (参数列表) -> {代码块; return **;}```
(参数列表) -> 单行代码(参数列表) -> {代码;}
(参数列表) -> {
代码;
return 返回值;
}(参数列表) -> {return 返回值;}
(参数列表) -> 返回值
3. Lambda表达式可以用在哪里: 在函数式接口上使用.
-
什么是函数式接口: 函数式接口就是仅有1个抽象方法的接口
- 注意只针对抽象方法数量进行限制.
- 一个接口即使包含很多默认/default方法,只有接口中只定义了1个抽象方法,依然是函数式接口.
- DefaultInterface虽然有很多默认方法,但仅包含1个抽象方法,也属于函数式接口.
@FunctionalInterface public interface DefaultInterface { void f1(); default void f2(){}; default void f3(){}; default void f4(){}; }
- 对于函数式接口,建议添加注解@FunctionalInterface ,但不是必须的.
-
Lambda表达式允许直接以内联的形式为函数式接口的抽象方法提供实现,并将整个Lambda表达式作为该函数式接口的1个实例.
- 由此可见,传递指定接口实例,使用匿名内部类,和使用Lambda表达式本质是一样的,都是传递1个"实例".
- Lambda表达式只是让代码更简洁.
-
函数式接口的抽象方法的签名基本上就上Lambda表达式的签名.
- 根据这个规则,对照函数式接口的’方法形式’,就可以写出对应的Lambda表达式
- (type p1,type p2, ***) -> { 方法体; }
@FunctionalInterface public interface FuncI1{ void f(); } @FunctionalInterface public interface FuncI2{ void f1(int p1,int p2); } private void testLambdaFuncSign() { //以Runnable为例 //Runnable就属于函数式接口 //@FunctionalInterface //public interface Runnable { Runnable r1 = new Runnable() { @Override public void run() { } }; Runnable r2 = () -> { }; //以自定义函数式接口为例 FuncI1 funcI11 = new FuncI1() { @Override public void f() { } }; FuncI1 funcI12 = () -> {}; FuncI2 funcI21 = new FuncI2() { @Override public void f1(int p1, int p2) { } }; FuncI2 funcI22 = (p1, p2) -> {}; }
4. Java8新增的函数式接口
-
Predicate
- Predicate接收泛型T实例,返回boolean值. T->boolean.
- Predicate常用于对流中的数据进行过滤,及其他根据1个实例返回boolean的场景
- 示例
@FunctionalInterface public interface Predicate<T> { boolean test(T t); } public class Person{ public String name = "Li Lei"; public String getName() { return name; } public void setName(String name) { this.name = name; } } @RequiresApi(api = Build.VERSION_CODES.N) public boolean testPerson(Person person, Predicate<Person> predicate){ return predicate.test(person); } @RequiresApi(api = Build.VERSION_CODES.N) public void testPredicate(){ Predicate<Person> personPredicate = person -> person.getName().equals("Han Meimei"); testPerson(new Person(),personPredicate); }
-
Consumer
- Consumer接收一个泛型T实例,无返回. T->void
- 从命名即可看出,单纯消费一个实例.
- 示例
@FunctionalInterface public interface Consumer<T> { //单纯地消费1个实例 void accept(T t); } @RequiresApi(api = Build.VERSION_CODES.N) public void testConsumer(){ List<String> list = Arrays.asList("1","2","3"); Consumer<String> consumer = s -> Log.d("TestConsumer","当前项:" + s); list.forEach(consumer); }
-
Function
- Function接收1个泛型T实例,返回1个泛型R实例. T->R
- 可以理解为常规的 输入->输出.
- 示例
@FunctionalInterface public interface Function<T, R> { //接收T实例,返回R实例 R apply(T t); } @RequiresApi(api = Build.VERSION_CODES.N) public void testFunction(){ /* Function<String, Integer> function = new Function<String, Integer>() { @Override public Integer apply(String s) { return Integer.parseInt(s); } }; */ //这里再次复习一下使用Lambda表达式表示 函数式接口实例 Function<String, Integer> function = s -> Integer.parseInt(s); int result = function.apply("1000"); }
-
Supplier
- Supplier不接收实例,直接生成一个泛型T实例. void->T
- 从名字就可以看出,是一个生产者
- 示例
@FunctionalInterface public interface Supplier<T> { T get(); } @RequiresApi(api = Build.VERSION_CODES.N) public void testSupplier() { Supplier<Person> supplier = () -> new Person(); Person person = supplier.get(); }
5. 方法引用
-
方法引用就是让你根据已有的方法来创建Lambda表达式.
-
方法引用的格式: 目标引用::方法名称
-
方法引用主要有3类
- 指向静态方法 的 方法引用
- 表现形式: className::func
- 指向任意类实例指定方法 的 方法引用
- 表现形式: className::func
- 指向现有实例的指定方法 的 方法引用
- 表现形式: instance::func
public class PersonOpt{ private String gainTag(Person person){ return "Tag" + person.getName(); } } @RequiresApi(api = Build.VERSION_CODES.N) public void testMethodReference() { //指向静态方法 的 方法引用 //这里指向的是Integer类的静态方法 //本质: className.func(param) //形式: className::func Function<String,Integer> f1 = (s) -> Integer.parseInt(s); Function<String,Integer> f2 = Integer::parseInt; //指向任意类实例指定方法 的 方法引用 //这里指向的就是Person类中的非静态方法 getName //本质: param.func() //形式: className::func Function<Person,String> f3 = (p) -> p.getName(); Function<Person,String> f4 = Person::getName; //指向现有实例的指定方法 的 方法引用 //这里指向的是PersonOpt实例的非静态方法personOpt //本质: instance.func(param) //形式: instance::func PersonOpt personOpt = new PersonOpt(); Function<Person,String> f5 = new Function<Person, String>() { @Override public String apply(Person person) { return personOpt.gainTag(person); } }; Function<Person,String> f6 = personOpt::gainTag; }
- 指向静态方法 的 方法引用
-
对构造函数的引用: ClassName::new
- 构造函数引用适合用于生产者/Supplier
- 构造函数的形式就是 void->T
@RequiresApi(api = Build.VERSION_CODES.N) public void testConstructorRef(){ Supplier<Person> supplier1 = new Supplier<Person>() { @Override public Person get() { return new Person(); } }; Supplier<Person> supplier2 = () -> new Person(); //public Person(){} 构造函数的形式就是 void -> T Supplier<Person> supplier3 = Person::new; }
-
Lambda表达式和方法引用怎么用
这里以1个自定义的需求为例.
我们使用的很多方法都是参数传入,结果返回.
比如输入3个参数,返回1个结果.
同样形式的方法有很多个:
public String f1(int p1,long p2, double p3){ return **; } public int f2(int p1,String p2,Person p3){ return **; } public Person f3(int p1,long p2,Dog dog){ return **; }
使用lambda表达式及函数引用,可以实现’形式上的复用’.降低代码量.
- 首先根据入参和返回结果的形式,创建对应的函数式接口.比如3个入参,返回1个结果,可以定义1个包含4个泛型数据的函数式接口.
- 然后使用Lambda表达式创建该函数式接口的对应实例即可.避免声明过多方法.
//1:构造1个函数式接口/只有1个抽象方法的接口 @FunctionalInterface public interface CustomInterface<Source,Param1,Param2,Result>{ Result gainResult(Source source,Param1 param1,Param2 param2); } //2:创建该函数式接口的实例 public void testCustomInterface(){ //原始形式创建 CustomInterface<String,Integer,Integer,String> c1 = new CustomInterface<String, Integer, Integer, String>() { @Override public String gainResult(String s, Integer param1, Integer param2) { return s.substring(param1,param2); } }; //lambda表达式创建 //(参数列表) -> {return result;} CustomInterface<String,Integer,Integer,String> c2 = (source,param1,param2) -> {return source.substring(param1,param2);}; //(参数列表) -> result CustomInterface<String,Integer,Integer,String> c3 = (source,param1,param2) -> source.substring(param1,param2); //直接使用方法引用 //className::func
设计模式学习笔记
设计模式系列学习视频
CodeChina开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》
ram2) -> source.substring(param1,param2);
//直接使用方法引用
//className::func
设计模式学习笔记
[外链图片转存中…(img-7Jt4nQAl-1630931419562)]
设计模式系列学习视频
[外链图片转存中…(img-U8D53lRV-1630931419564)]