Lambda 表达式
作用
为了简化匿名内部类的书写
本质
本质就是一个接口的对象
前提
必须是一个函数式接口。
注意:函数式接口就是只有一个抽象方法的接口。函数式接口都有一个统一的注释@FunctonalInterface
格式
(参数列表)->{}
格式的解释:
(参数列表):这个是放方法参数的方法
->:就是一个符号,表明了这是个Lambda表达式
{}:函数式接口中的抽象方法的方法体,也叫Lambda体
实例
package top.zunmx.u1;
// ALC-Master
@FunctionalInterface // 只能有一个抽象方法
interface A {
public abstract void a();
// public abstract void b();
public static void b() {
System.out.println("A-b");
}
}
public class Demo {
public static void main(String[] args) {
// AnonymousInnerClass?
new A() {
@Override
public void a() {
System.out.println("匿名内部类方式!");
}
}.a();
// Lambda
A a = ()->{
System.out.println("Lambda表达式方式");
};
a.a();
}
}
package top.zunmx.u1;
@FunctionalInterface
interface B{
public abstract void show(String text);
}
// ALC-Master
public class Demo2 {
public static void main(String[] args) {
B b = (sss)->{
System.out.println(sss);
};
b.show("123");
B c = abc ->{
System.out.println(abc);
};
c.show("321");
}
}
package top.zunmx.u1;
@FunctionalInterface
interface C {
public abstract void show(int a, int b);
}
// ALC-Master
public class Demo3 {
public static void main(String[] args) {
C c = (a, b) -> {
System.out.println(a + b);
};
c.show(5,3);
}
}
package top.zunmx.u1;
// ALC-Master
interface D {
public abstract int show(int a, int b);
}
public class Demo4 {
public static void main(String[] args) {
D d = (a, b) -> {
return a + b;
};
System.out.println(d.show(3, 7));
}
}
package top.zunmx.u1;
// 大括号和return可以要么省略,要么就全部保留
interface D {
public abstract int show(int a, int b);
}
public class Demo4 {
public static void main(String[] args) {
D d = (a, b) -> a + b;
System.out.println(d.show(3, 7));
}
}
package top.zunmx.u1;
// 如果大括号只有一条语句,还是省
interface E {
public abstract void show(String s);
}
public class Demo5 {
public static void main(String[] args) {
E e = (abc) -> System.out.println("hello:" + abc);
e.show("!!!");
}
}
注意事项
- 如果小括号中只有一个参数,那么可以省略小括号
- 如果打括号中只有一条输出语句,那么可以省略大括号
- 如果大括号中只有一条语句,并且是return 语句,那么可以同时省略return和大括号。
函数式接口
接口中只有一个抽象方法
注解:@FunctionalInterface
根据需求我们得出了以上的方法声明,但是这个方法声明是有问题的。因为在之前我们写一个方法的时候,只需要将参数a和b传递进去就可以使用了,但是现在我们不仅需要传递参数a和b,还需要传入对a和b的操作(也就是对a和b操作的方法),但是方法上是不能传递方法当做参数的,怎么办?Java官方给了折中的方法,我们不用在方法上传递方法了,而是在方法上传递一个接口(传递的是一个接口,实际上传递的是该接口的对象),接口中有抽象方法,可以让这个抽象方法做对a和b的操作。(注意:因为接口中的抽象方法必须要被重写才能使用,可以在方法重写的时候让它不同的功能)
常见的函数式接口
- 消费型接口---Consumer
- 供给型接口---Supplier
- 函数型接口---Function
- 断言型接口---Predicate
消费性接口Consumer
只接收数据并处理数据,但是不产生返回值
构造
public interface Consumer<T>;
方法
void accept(T t) ;
//对给定的参数执行此操作。
实例
package top.zunmx.d1;
import java.util.function.Consumer;
// ALC-Master
//function 1_1 start 创建一个子类,实现Consumer接口
class ConsumerImpl implements Consumer<Integer> {
@Override
public void accept(Integer t) {
System.out.println("F1小明拿了" + t + "元钱啊,买了个大宝剑");
}
}
// function1_1 end
public class Demo2 {
public static void wasteMoney(int money, Consumer<Integer> con) { // 要的是接口,实际上要的是该接口的对象昂
con.accept(money);
}
public static void main(String[] args) {
// function 1_2 创建要给子类实现Consumer接口
ConsumerImpl ci = new ConsumerImpl();
wasteMoney(100, ci);
// function 1_2 end
// function 2 使用匿名内部类
Consumer<Integer> consumer = new Consumer<Integer>() {
public void accept(Integer t) {
System.out.println("F2小明拿了" + t + "元钱啊,买了个大宝剑");
};
};
wasteMoney(200, consumer);
// function 2 end
// function 3 使用lambda 表达式
Consumer<Integer> con = (x) -> System.out.println("F3小明拿了" + x + "元钱啊,买了个大宝剑");
wasteMoney(300, con);
// function 3 end
// function 4 复合Lambda
wasteMoney(400, x -> System.out.println("F4小明拿了" + x + "元钱啊,买了个大宝剑"));
// function 4 end
}
}
供给型接口Supplier
构造
public interface Supplier<T>
接口中的抽象方法必须要参数,而只产生返回值
方法
T get()
获得结果。
实例
package top.zunmx.d2;
import java.util.ArrayList;
import java.util.Random;
import java.util.function.Supplier;
// ALC-Master
public class Demo {
public static ArrayList<Integer> getter(int size, Supplier<Integer> sal) {
ArrayList<Integer> al = new ArrayList<Integer>();
for (int i = 0; i < size; i++) {
al.add(sal.get());
}
return al;
}
public static void main(String[] args) {
Supplier<Integer> supplier = new Supplier<Integer>() {
@Override
public Integer get() {
return new Random().nextInt(51) + 30;
}
};
ArrayList<Integer> v = getter(5, supplier);
System.out.println(v);
ArrayList<Integer> v2 = getter(10, () -> new Random().nextInt(51) + 30);
System.out.println(v2);
}
}
函数型接口Function
构造
public interface Function<T,R>
表示接受一个参数并产生结果的函数。
方法
R apply(T t)
将此函数应用于给定的参数。
package top.zunmx.d3;
import java.awt.PrintGraphics;
import java.util.function.Function;
// ALC-Master
public class Test {
public static int getNum(int num, Function<Integer, Integer> fun) {
return fun.apply(num);
}
public static void main(String[] args) {
Function<Integer, Integer> fun = new Function<Integer, Integer>() {
@Override
public Integer apply(Integer t) {
return 2 * t;
}
};
System.out.println(getNum(5, fun));
Function<Integer, Integer> fun2 = (x) -> {
return x * x;
};
System.out.println(getNum(5, fun2));
System.out.println(getNum(5, x -> x * x * x));
}
}
断言型接口Predicate
接受一个数据,并做出判断得到一个boolean类型的结果
方法
boolean test(T t)
在给定的参数上评估这个谓词。
实例
package top.zunmx.d4;
import java.security.AllPermission;
import java.util.ArrayList;
import java.util.function.Predicate;
// ALC-Master
public class Demo {
public static void main(String[] args) {
ArrayList<Integer> al = new ArrayList<Integer>();
al.add(1);
al.add(2);
al.add(3);
al.add(4);
al.add(5);
al.add(6);
Predicate<Integer> pre = new Predicate<Integer>() {
@Override
public boolean test(Integer t) {
return t % 2 == 0;
}
};
ArrayList<Integer> rstAL = getArrayList(al, pre);
System.out.println(rstAL);
// Lambda
System.out.println(getArrayList(al, (t) -> t % 2 != 0));
}
/*
* 返回值类型:集合 ArrayList<Integer> 参数列表:ArrayList<Integer> al ,Predicate<Integer>
* pre
*
*/
public static ArrayList<Integer> getArrayList(ArrayList<Integer> al, Predicate<Integer> pre) {
// 1. 创建集合,用来存储筛选之后的数据
ArrayList<Integer> list = new ArrayList<Integer>();
// 2. 遍历传入的集合
for (Integer i : al) {
/*
* 3. 判断集合中的每个元素是奇数还是偶数
*
* 判断就的操作是在test方法中进行,但是还没有重写,重写后就有了 将Predicate 对象传递过来的时候就重写好了
*/
if (pre.test(i)) {
list.add(i);
}
}
return list;
}
}
方法的引用
之前学习的函数式接口当作一个事情的解决方案来使用的(并且这个解决方案是以参数传递到方法中的),既然是一个解决方案了,但是Java中已经有了相同或类似的解决方案,那么我们就可以不用写了,而是直接使用Java官方提供好的解决方案就可以了(当作参数传递)。这种使用Java官方提供好的解决方案的行为被称为方法的引用。
方法引用的符号:
::
使用普通的方法
对象名::方法名
使用静态的方法
类名::方法名
实例
package top.zunmx.d5;
import java.util.function.Consumer;
// ALC-Master
public class Demo {
public static void main(String[] args) {
// 函数式接口+Lambda方式
String str = "Hello";
Consumer<String> con = (x) -> {
System.out.println(x);
};
waste(str, con);
// 方法引用
waste(str, System.out::println);
}
public static void waste(String s, Consumer<String> con) {
con.accept(s);
}
}
package top.zunmx.d5;
import java.util.function.Supplier;
// ALC-Master
public class Demo2 {
public static void main(String[] args) {
// 函数式接口 + Lambda
Supplier<Double> sup = () -> Math.random();
System.out.println(getRandom(sup));
// 方法引用的方式
System.out.println(getRandom(Math::random));
}
// 此处函数式接口 Supplier 的作用为提供一个数
public static double getRandom(Supplier<Double> sup) {
return sup.get();
}
}
什么时候使用方法引用
- 方法引用是为了简化冗余的Lambda表达式代码
- 如果函数式接口和Lambda中已经有定义好的了,就可以使用定义好的解决方案,就不用函数式接口和Lambda表达式再去自己重新写了。这样既简化了代码,也提升了代码的美观性。
StreamAPI
在JDK8之后出来,用来简化对集合的操作
获取Stream对象
- 单列集合获取Stream对象
stream();
```
2. 双列集合获取Stream对象
```java
keySet().stream();
values().stream();
entrySet().stream();
```
3. 数组获取Stream对象
Stream.of(T t);
```
```java
package top.zunmx.d6;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.stream.Stream;
// ALC-Master
public class Demo {
private void mian() {
ArrayList al = new ArrayList();
Stream alStream = al.stream();
HashMap hm = new HashMap();
Stream hmkStream = hm.keySet().stream();
Stream hmvStream = hm.values().stream();
Stream<Entry> hmeStream = hm.entrySet().stream();
int[] arr = new int[3];
Stream<int[]> arrStream = Stream.of(arr);
}
}
```
## 常见方法
java
long count() ;
//返回此流中的元素数。
void forEach(Consumer<? super T> action) ;
//对此流的每个元素执行操作。
Stream<T> filter(Predicate<? super T> predicate) ;
//返回由与此给定谓词匹配的此流的元素组成的流。
Stream<T> limit(long maxSize) ;
//返回由此流的元素组成的流,截短长度不能超过 maxSize 。
Stream<T> skip(long n) ;
//在丢弃流的第一个 n元素后,返回由该流的 n元素组成的流。
```java
package top.zunmx.d6;
import java.util.ArrayList;
import java.util.stream.Stream;
import javax.security.auth.x500.X500Principal;
// ALC-Master
public class Demo2 {
public static void main(String[] args) {
ArrayList al = new ArrayList();
al.add("杨过");
al.add("杨光");
al.add("张晓光");
al.add("小龙女");
al.add("施立旋");
al.add("杨癫疯");
// start
Stream stream = al.stream();
System.out.println(stream.count());
// end
System.out.println();
// start
stream = al.stream();
stream.forEach(System.out::println);
// or
al.forEach(System.out::println);
// end
System.out.println();
// start
stream = al.stream();
stream.filter(x -> x.charAt(0) == '杨').forEach(System.out::println);
// end
System.out.println();
// start
stream = al.stream();
stream.limit(3).forEach(System.out::println);
// end
System.out.println();
// start
stream = al.stream();
stream.skip(2).forEach(System.out::println);
// end
}
}
```

评论 0
还没有评论,来说点什么吧。