一基础知识
lambda 表达式本质上就是匿名方法, 该方法不是独立执行的, 而是用于实现由函数式接口定义的方法, 函数式接口仅包含一个抽象方法的接口
无参数 lambda 表达式
- class Solution {
- interface MyNumber {
- double getValue();
- }
- public static void main(String[] args) {
- MyNumber number = () -> 100;
- System.out.println(number.getValue());
- }
- }
- View Code
带参数 lambda 表达式
- class Solution {
- interface MyNumber {
- boolean isFactor(int a, int b);
- }
- public static void main(String[] args) {
- MyNumber number = (a, b) -> a % b == 0;
- System.out.println(number.isFactor(10, 5));
- }
- }
- View Code
块 lambda 表达式
- class Solution {
- interface MyNumber {
- double getAvr(double... arr);
- }
- public static void main(String[] args) {
- MyNumber number = (arr) -> {
- double res = 0;
- for (double i : arr)
- res += i;
- res /= arr.length;
- return res;
- };
- double res = number.getAvr(1.0, 2.0, 3.0, 4.0, 5.0);
- System.out.println(res);
- }
- }
- View Code
二泛型函数式接口
- class Solution {
- interface MyNumber<T extends Number> {
- T getAvr(T... arr);
- }
- public static void main(String[] args) {
- MyNumber<Double> number = (arr) -> {
- double res = 0;
- for (double i : arr)
- res += i;
- res /= arr.length;
- return res;
- };
- double res = number.getAvr(1.0, 2.0, 3.0, 4.0, 5.0);
- System.out.println(res);
- }
- }
- View Code
三参数传递
可以 lambda 表达式作为参数传递给方法, 为了将 lambda 表达式作为参数传递, 接收 lambda 表达式的类型必须是与该 lambda 表达式兼容的函数式接口的类型
- class Solution {
- interface MyString {
- String reverse(String s);
- }
- static String strOperate(MyString sf, String s) {
- return sf.reverse(s);
- }
- public static void main(String[] args) {
- String str = "Hello World";
- MyString sf = (s) -> {
- StringBuilder builder = new StringBuilder(s);
- return builder.reverse().toString();
- };
- System.out.println(strOperate(sf, str));
- }
- }
- View Code
四异常
lambda 表达式支持抛出异常, 但是如果抛出经检查的异常, 就必须与函数式接口的抽象方法 throws 语句所列出的异常兼容
- class Solution {
- static class EmptyArrayException extends Exception {
- EmptyArrayException() {
- super("Empty Array");
- }
- }
- interface MyNumber {
- double getAvr(double... arr) throws EmptyArrayException;
- }
- public static void main(String[] args) {
- MyNumber number = (arr) -> {
- if (arr.length == 0)
- throw new EmptyArrayException();
- double res = 0;
- for (double i : arr)
- res += i;
- res /= arr.length;
- return res;
- };
- try {
- double res = number.getAvr();
- System.out.println(res);
- } catch (EmptyArrayException exc) {
- System.out.println(exc.getMessage());
- }
- }
- }
- View Code
五变量捕获
lambda 表达式中可以访问其外层作用域内定义的变量, 但是这是会产生一种特殊情况, 称为变量捕获在这种情况下, lambda 表达式只能使用实质上 final 的局部变量 final 局部变量指的是第一次赋值之后值不能再发生变化的变量, 这意味着 lambda 表达式不能修改外层作用域内的局部变量, 即不能改变基本类型或者引用类型的数值, 但是可以调用引用类型的方法
六方法引用
静态方法引用
- class Solution {
- interface MyString {
- String reverse(String s);
- }
- static String strReverse(String s) {
- StringBuilder builder = new StringBuilder(s);
- return builder.reverse().toString();
- }
- static String strOperate(MyString sf, String s) {
- return sf.reverse(s);
- }
- public static void main(String[] args) {
- String str = "Hello World";
- System.out.println(strOperate(Solution::strReverse, str));// 传递方法引用
- }
- }
- View Code
实例方法引用
- class Solution {
- interface MyString {
- String reverse(String s);
- }
- String strReverse(String s) {
- StringBuilder builder = new StringBuilder(s);
- return builder.reverse().toString();
- }
- static String strOperate(MyString sf, String s) {
- return sf.reverse(s);
- }
- public static void main(String[] args) {
- Solution solution = new Solution();
- String str = "Hello World";
- System.out.println(strOperate(solution::strReverse, str));// 传递方法引用
- }
- }
- View Code
泛型方法引用
- class Solution {
- interface MyArray<T> {
- boolean contain(T[] arr, T x);
- }
- static <T> boolean arrContain(T[] arr, T x) {
- for (T i : arr)
- if (i.equals(x))
- return true;
- return false;
- }
- static <T> boolean arrOperate(MyArray<T> af, T[] arr, T x) {
- return af.contain(arr, x);
- }
- public static void main(String[] args) {
- Integer[] arr = {1, 2, 3, 4, 5};
- System.out.println(arrOperate(Solution::<Integer>arrContain, arr, 0));
- }
- }
- View Code
构造函数引用
- interface MyInterface {
- MyClass constructor(int val);
- }
- class MyClass {
- private int val;
- MyClass(int val) {
- this.val = val;
- }
- MyClass() {
- val = 0;
- }
- int getVal() {
- return val;
- }
- }
- class Solution {
- public static void main(String[] args) {
- MyInterface mf = MyClass::new;// 匹配 MyClass(int val)
- MyClass mc = mf.constructor(100);
- System.out.println(mc.getVal());
- }
- }
- View Code
泛型构造函数引用
- interface MyInterface<T> {
- MyClass constructor(T val);
- }
- class MyClass<T> {
- private T val;
- MyClass(T val) {
- this.val = val;
- }
- T getVal() {
- return val;
- }
- }
- class Solution {
- public static void main(String[] args) {
- MyInterface<Double> mf = MyClass::new;
- MyClass mc = mf.constructor(100.0);
- System.out.println(mc.getVal());
- }
- }
- View Code
七预定义函数式接口
通常我们不需要自己定义函数式接口, Java 已经提供了一些预定义的函数式接口
UnaryOperator<T> | 对类型为 T 的对象应用一元运算并返回结果,方法名为 apply。 |
BinaryOperator<T> | 对类型为 T 的两个对象进行操作并返回结果,方法名为 apply。 |
Consumer<T> | 对类型为 T 的对象应用操作,方法名为 accept。 |
Supplier<T> | 返回类型为 T 的对象,方法名为 get。 |
Function<T, R> | 对类型为 T 的对象应用操作,并返回类型为 R 的对象,方法名为 apply。 |
Predicate<T> | 确定类型为 T 的对象是否满足某种约束,返回布尔值,方法名为 test。 |
预定义函数式接口使用
- import java.util.function.BinaryOperator;
- class Solution {
- public static void main(String[] args) {
- BinaryOperator<Integer> op = (a, b) -> a + b;
- System.out.println(op.apply(10, 100));//110
- }
- }
- View Code
来源: http://www.bubuko.com/infodetail-2502239.html