当前位置:   article > 正文

jdk8新特性之Lambda_jalab 8

jalab 8

Lambda

使用Lambda的好处

Lambda表达式好处:简化我们匿名内部类的调用

Java中使用Lambda表达式的规范,必须是为函数接口

函数接口定义

JDK 1.8 版本以上有效

@FunctionalInterface 语法格式严格要求当前接口【有且只能有一个】尚未完成的 缺省属性为 public abstract 修饰方法。

Lambda 表达式和 方法引用使用的前提!!!

函数式接口一般用于方法的增强,直接作为方法的参数,实现【插件式编程】。

//代码示例
   @FunctionalInterface
   interface Test {
      void test();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
Lambda基础语法

基本格式:(函数接口中方法的参数列表,只需写参数名称) -> { 方法体}

Lambda 表达式关注的是接口中方法的【返回值】和【参数】

使用Lambda 方法体中只有一条语句的情况下,在这时候我们不需要写{} 也可以不需要写return

1. 无参数无返回值 Lambda

接口设计

@FunctionalInterface
interface A {
	void 方法名真的没有用();
}
  • 1
  • 2
  • 3
  • 4

方法设计

/**
 * Lambda 测试方法,当前方法所需参数是 A 接口实例化对象,因为当前 A 接口
 * 是一个函数式接口,可以使用 Lambda 表达式解决问题
 *
 * @param a 函数式接口 A
 */
public static void testLambda(A a) {
    a.方法名真的没有用();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

代码实现

public static void main(String[] args) {
    /*
    1. 匿名内部类方式
     */
    testLambda(new A() {
        @Override
        public void 方法名真的没有用() {
            System.out.println("无参数返回值 匿名内部类对象方法实现");
        }
    });

    /*
    2. Lambda 表达式实现
    【分析】
        void 方法名真的没有用();
        接口方法【返回值】 void
        接口方法【参数】 无参数
     Lambda 格式
        () -> {大括号中无需返回值类型}
     */
    testLambda(() -> {
        System.out.println("Lambda 表达式初体验");
    });

    // 【注意】Lambda 表达式有且只有一行代码,可以省略大括号
    testLambda(() -> System.out.println("Lambda 表达式初体验"));

    // 方法引用方式
    testLambda(Demo1::test);
}

public static void test() {
    System.out.println("方法引用");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
2. 有参数无返回值 Lambda

接口设计

Consumer 消费者接口,数据最终处理接口,数据处理终止方法接口…因为当前接口中,数据有去无回

泛型可以在使用过程中,支持数据类型多样性,同时满足数据类型一致化要求!当前方法可以支持的数据类型满足所有情况。

@FunctionalInterface
public interface Consumer<T> {
    /**
    * 消费者接口,数据最终处理接口,数据处理终止方法接口,对应的方法要求
    * 方法有参数无返回值
    *
    * @param t 泛型数据数据类型 T ,支持任意类型,在接口约束之后,要求符合
    *			数据类型一致化要求
    */
    void accept(T t);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

方法设计

/**
 * 有参数无返回 Lambda 测试方法,方法参数是 String 类型和针对于 String 类型
 * 进行数据处理的 Consumer 接口,Consumer 接口可以传入实现类对象和 Lambda 表
 * 达式
 *
 * @param str    目标处理的 String 字符串数据
 * @param handle 已经约束为处理 String 类型数据的 Consumer 接口处理器
 */
public static void testLambda(String str, Consumer<String> handle) {
    /*
    需要方法外部提供针对于当前 String 字符串的处理能力。
    处理能力通过 Consumer 接口传入
     */
    handle.accept(str);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

代码实现

public static void main(String[] args) {
    /*
    1、匿名内部类 Low
     */
    testLambda("孟州市炒面第一名", new Consumer<String>() {
        @Override
        public void accept(String t) {
            System.out.println(t);
        }
    });

    /*
    2. Lambda 表达式
    【分析】
        void accept(T t); ==> 泛型约束为 String ==> void accept(String t);
        接口方法【返回值】 void
        接口方法【参数】 1 个参数,String 类型
     Lambda 格式
        Lambda 小括号中的临时变量名称,没有数据类型体现,需要【联想】目标方法数据类型
        只按照参数的个数定义临时小变量
        (s) -> {大括号中无需返回值类型}
            Lambda 表达式临时变量 s 对应的数据类型为 String 类型 【联想可得】
     */
    testLambda("lambda表达式需要联想!!!", (s) -> {
        System.out.println(Arrays.toString(s.toCharArray()));
    });

    /*
    Lambda 优化
        1. 代码块有且只有一行,可以省略大括号
        2. 小括号中有且只有一个 参数,可以省略小括号

    【注意】
        Lambda 承担的角色是一个针对于 String 字符串的处理器
     */
    testLambda("lambda表达式需要联想!!!", s -> System.out.println(Arrays.toString(s.toCharArray())));

    // 方法引用
    testLambda("lambda表达式需要联想!!!", System.out::println);
    testLambda("lambda表达式需要联想!!!", Demo2::test);

}

public static void test(String str) {
    System.out.println(str);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
3. 无参数有返回值 Lambda

生产者接口

巧妇难为无米之炊,使用的数据都是对应方法中的数据内容,利用方法【局部变量 Local Variable】

接口设计

@FunctionalInterface
interface Supplier<T> {
    /**
    * 无参数有返回值方法,泛型约束的是接口对应的返回值数据类型,要求
    * 按照泛型约束返回对应的数据内容
    *
    * @return 返回一个数据,符合泛型约束
    */
	T get();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

方法设计

/**
 * 当前方法要求返回一个字符串数据内容
 *
 * @param s Supplier 生产者,数据提供接口对应的参数
 * @return 字符串数据
 */
public static String testLambda(Supplier<String> s) {
    return s.get();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

代码实现

public static void main(String[] args) {
    /*
    1. 匿名内部类形式
     */
    String s = testLambda(new Supplier<String>() {
        @Override
        public String get() {
            return "这是一个字符串";
        }
    });

    System.out.println(s);

    /*
     /*
    2. Lambda 表达式
    【分析】
        T get(); ==> 泛型约束为 String ==> String get();
        接口方法【返回值】 String
        接口方法【参数】 无参数
     Lambda 格式
        () -> {必须返回一个 String 类型}
            return 关键字出马
     */
    String s1 = testLambda(() -> {
        return "这里也是一个字符串";
    });
    System.out.println(s1);

    /*
    Lambda 优化,只要 -> 之后是一个 字符串数据内容就可以满足当前 Lambda 所需
    可以省略 return ,前提是当前 Lambda 有且只有一行代码
     */
    String s2 = testLambda(() -> "这里也是一个字符串");
    System.out.println(s2);

    /*
    Lambda 内部使用使用方法局部变量
     */
    String str = "name=周冠宇&age=23&country=中国";
    String s3 = testLambda(() -> {
        // str 是当前 main 方法局部变量,Lambda 内部可以直接使用
        String[] split = str.split("&");
        return split[0];
    });
    System.out.println(s3);

    // 方法引用
    String s4 = testLambda(Demo3::test);
    System.out.println(s4);
}

public static String test() {
    return "Function Reference";
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
4. 有参数有返回值 Lambda

相关接口设计

比较器接口

@FunctionalInterface
interface Comparator<T> {
    /**
     * 比较器接口要求的方法,参数是泛型参数,用户指定类型
     *
     * @param o1 用户在使用接口时约束的泛型对应具体数据类型参数
     * @param o2 用户在使用接口时约束的泛型对应具体数据类型参数
     * @return 返回值为 int 类型,0 表示两个元素一致。
     */
    int compare(T o1, T o2);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

比较器案例代码

public class Demo5 {
    public static void main(String[] args) {
        Person[] array = new Person[5];

        for (int i = 0; i < array.length; i++) {
            int age = (int) (Math.random() * 50);
            array[i] = new Person(i + 1, "张三", age, false);
        }

        /*
        Lambda 分析
            boolean test(T t); ==> 泛型约束为 Person 类型 ==> boolean test(Person t);
        方法返回值是 boolean
        方法参数
            1. 1 个
            2. Person 类型
         Lambda 格式
            p -> {要求必须返回一个 boolean}
         */
        Person[] temp = filterPersonArrayUsingPredicate(array, p -> p.getAge() > 10);

        for (Person person : temp) {
            System.out.println(person);
        }

    }

    /**
     * 过滤限定操作,利用 Predicate 过滤器接口限定数组内容
     *
     * @param array  Person 类型数组
     * @param filter Predicate 过滤器参数
     * @return 过滤限定之后的新数组
     */
    public static Person[] filterPersonArrayUsingPredicate(Person[] array, Predicate<Person> filter) {
        Person[] temp = new Person[array.length];

        int count = 0;
        for (int i = 0; i < array.length; i++) {
            /*
             Predicate 接口提供的方法是  boolean test(T t);
             目前泛型约束之后是 boolean test(Person t);
             判断当前 Person 对象是否满足要求,如果满足,存储到 temp 数组中。
             */
            if (filter.test(array[i])) {
                temp[count++] = array[i];
            }
        }

        return temp;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

过滤器接口

// 过滤器接口,判断器接口,条件接口
@FunctionalInterface
interface Predicate<T> {
    /**
     * 过滤器接口约束的方法,方法参数是用户使用时约束泛型对应具体数据参数
     * 返回值类型是 boolean 类型,用于条件判断,数据过来
     *
     * @param t 用户约束泛型对应的具体数据类型参数
     * @return boolean 数据,判断结果反馈
     */
    boolean test(T t);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

过滤器接口案例代码

public class Demo5 {
    public static void main(String[] args) {
        Person[] array = new Person[5];

        for (int i = 0; i < array.length; i++) {
            int age = (int) (Math.random() * 50);
            array[i] = new Person(i + 1, "张三", age, false);
        }

        /*
        Lambda 分析
            boolean test(T t); ==> 泛型约束为 Person 类型 ==> boolean test(Person t);
        方法返回值是 boolean
        方法参数
            1. 1 个
            2. Person 类型
         Lambda 格式
            p -> {要求必须返回一个 boolean}
         */
        Person[] temp = filterPersonArrayUsingPredicate(array, p -> p.getAge() > 10);

        for (Person person : temp) {
            System.out.println(person);
        }

    }

    /**
     * 过滤限定操作,利用 Predicate 过滤器接口限定数组内容
     *
     * @param array  Person 类型数组
     * @param filter Predicate 过滤器参数
     * @return 过滤限定之后的新数组
     */
    public static Person[] filterPersonArrayUsingPredicate(Person[] array, Predicate<Person> filter) {
        Person[] temp = new Person[array.length];

        int count = 0;
        for (int i = 0; i < array.length; i++) {
            /*
             Predicate 接口提供的方法是  boolean test(T t);
             目前泛型约束之后是 boolean test(Person t);
             判断当前 Person 对象是否满足要求,如果满足,存储到 temp 数组中。
             */
            if (filter.test(array[i])) {
                temp[count++] = array[i];
            }
        }

        return temp;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

类型转换器接口

// 类型转换器接口
@FunctionalInterface
interface Function<T, R> {
	R apply(T t);	
}
  • 1
  • 2
  • 3
  • 4
  • 5

代码实现

public class Demo6 {
    public static void main(String[] args) {
        String str = "开封有个包青天";

        /*
        Lambda 分析
            R apply(T t); ==> 泛型约束 T => String R => Integer
            Integer apply(String t);

        Lambda 格式
            返回值类型 Integer
            方法参数
                1. 1个
                2. String
            s -> {必须返回 int 类型数据}
         */
        int i = testLambda(str, s -> s.length());
        System.out.println(i);

        // 方法引用
        int ret =  testLambda("邠州有个范仲淹", Demo6::test);
        System.out.println(ret);

    }

    public static int testLambda(String str, Function<String, Integer> fun) {
        return fun.apply(str);
    }

    public static int test(String str) {
        return str.length();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/726789
推荐阅读
相关标签
  

闽ICP备14008679号