Loading... # Lambda 表达式 ## 作用 为了简化匿名内部类的书写 ## 本质 本质就是一个接口的对象 ## 前提 必须是一个函数式接口。 注意:函数式接口就是只有一个抽象方法的接口。函数式接口都有一个统一的注释@FunctonalInterface ## 格式 ``` (参数列表)->{} 格式的解释: (参数列表):这个是放方法参数的方法 ->:就是一个符号,表明了这是个Lambda表达式 {}:函数式接口中的抽象方法的方法体,也叫Lambda体 ``` ## 实例 ```java 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(); } } ``` ```java 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"); } } ``` ```java 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); } } ``` ```java 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)); } } ``` ```java 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)); } } ``` ```java 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("!!!"); } } ``` ## 注意事项 1. 如果小括号中只有一个参数,那么可以省略小括号 2. 如果打括号中只有一条输出语句,那么可以省略大括号 3. 如果大括号中只有一条语句,并且是return 语句,那么可以同时省略return和大括号。 # 函数式接口 接口中只有一个抽象方法 注解:@FunctionalInterface 根据需求我们得出了以上的方法声明,但是这个方法声明是有问题的。因为在之前我们写一个方法的时候,只需要将参数a和b传递进去就可以使用了,但是现在我们不仅需要传递参数a和b,还需要传入对a和b的操作(也就是对a和b操作的方法),但是方法上是不能传递方法当做参数的,怎么办?Java官方给了折中的方法,我们不用在方法上传递方法了,而是在方法上传递一个接口(传递的是一个接口,实际上传递的是该接口的对象),接口中有抽象方法,可以让这个抽象方法做对a和b的操作。(注意:因为接口中的抽象方法必须要被重写才能使用,可以在方法重写的时候让它不同的功能) ## 常见的函数式接口 - 消费型接口---Consumer - 供给型接口---Supplier - 函数型接口---Function - 断言型接口---Predicate ### 消费性接口Consumer 只接收数据并处理数据,但是不产生返回值 构造 ```Java public interface Consumer<T>; ``` 方法 ```java void accept(T t) ; //对给定的参数执行此操作。 ``` 实例 ```java 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() 获得结果。 ``` 实例 ```java 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 构造 ```java public interface Function<T,R> 表示接受一个参数并产生结果的函数。 ``` 方法 ```java R apply(T t) 将此函数应用于给定的参数。 ``` ```java 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) 在给定的参数上评估这个谓词。 ``` 实例 ```java 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官方提供好的解决方案的行为被称为方法的引用。 方法引用的符号: ```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); } } ``` ```java 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(); } } ``` ### 什么时候使用方法引用 > 1. 方法引用是为了简化冗余的Lambda表达式代码 > 2. 如果函数式接口和Lambda中已经有定义好的了,就可以使用定义好的解决方案,就不用函数式接口和Lambda表达式再去自己重新写了。这样既简化了代码,也提升了代码的美观性。 # StreamAPI 在JDK8之后出来,用来简化对集合的操作 ## 获取Stream对象 1. 单列集合获取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<String> al = new ArrayList<String>(); Stream<String> alStream = al.stream(); HashMap<String,String> hm = new HashMap<String, String>(); Stream<String> hmkStream = hm.keySet().stream(); Stream<String> hmvStream = hm.values().stream(); Stream<Entry<String, String>> 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<String> al = new ArrayList<String>(); al.add("杨过"); al.add("杨光"); al.add("张晓光"); al.add("小龙女"); al.add("施立旋"); al.add("杨癫疯"); // start Stream<String> 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 } } ``` © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏