深入浅出理解Java Lambda表达式之四大核心函数式的用法与范例

目录
  • 1.四大核心函数式接口
    • 1.1 Consumer<T> : 消费型接口
    • 1.2 Supplier<T> : 供给型接口
    • 1.3 Function<T, R> : 函数型接口
    • 1.4 Predicate<T> : 断言型接口
  • 2.方法引用
    • 2.1 对象 :: 实例方法
    • 2.2 类 :: 静态方法
    • 2.3 类 :: 实例方法
  • 3.构造器引用
  • 4.数组引用

1.四大核心函数式接口

上一篇文章中说到了Lambda表达式中的基本语法,以及我们如何自定义函数式接口。但是在写代码的过程中,大家可能会发现一个问题:当我们有一个新的需求时,可以去自定义一个函数式接口,然后再创建一个它的实现类定义一些相关的业务逻辑行为。那么如果说我们有很多需求、这些需求可能还会不断地变化,那么我们岂不是每次都要去创建新的实现类、同时再去修改之前创建好的实现类中的业务代码?这可太麻烦了吧。。。

所以呢,Java8就为我们提供了四大核心函数式接口,使用起来非常的方便。

1.1 Consumer<T> : 消费型接口

package com.szh.java8;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/*
 *
 */
public class MyTest3 {

    //Consumer<T> : 消费型接口
    @Test
    public void test1() {
        happy(6666.66,(m) -> System.out.println("本地双11共消费 " + m + " 元!!!"));
    }

    public void happy(double money, Consumer<Double> consumer) {
        consumer.accept(money);
    }

}

1.2 Supplier<T> : 供给型接口

package com.szh.java8;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/*
 *
 */
public class MyTest3 {

    //Supplier<T> : 供给型接口
    @Test
    public void test2() {
        List<Integer> numList = getNumList(10, () -> (int)(Math.random() * 100));
        for (Integer num : numList) {
            System.out.println(num);
        }
    }

    public List<Integer> getNumList(int num, Supplier<Integer> supplier) {
        List<Integer> list = new ArrayList<>();

        for (int i = 0; i < num; i++) {
            Integer n = supplier.get();
            list.add(n);
        }

        return list;
    }

}

1.3 Function<T, R> : 函数型接口

package com.szh.java8;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/*
 *
 */
public class MyTest3 {

    //Function<T, R> : 函数型接口
    @Test
    public void test3() {
        String trimStr = strHandler("\t\t\t  张起灵-小哥   ", (str) -> str.trim());
        System.out.println(trimStr);

        String newStr = strHandler("我喜欢看盗墓笔记呀!!!",(str) -> str.substring(4,8));
        System.out.println(newStr);
    }

    public String strHandler(String str, Function<String,String> function) {
        return function.apply(str);
    }

}

1.4 Predicate<T> : 断言型接口

package com.szh.java8;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/*
 *
 */
public class MyTest3 {

    //Predicate<T> : 断言型接口
    @Test
    public void test4() {
        List<String> list = Arrays.asList("Hello","张起灵-小哥","HashMap","jdk8","List","Set");
        List<String> stringList = filterStr(list, (s) -> s.length() > 5);

        for (String string : stringList) {
            System.out.println(string);
        }
    }

    public List<String> filterStr(List<String> strings, Predicate<String> predicate) {
        List<String> strList = new ArrayList<>();

        for (String str : strings) {
            if (predicate.test(str)) {
                strList.add(str);
            }
        }

        return strList;
    }
}

除此之外,还有一些其他的函数式接口,它们有一部分是上面提到的四大核心函数式接口的子接口。

2.方法引用

当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用! 方法引用:使用操作符 “ :: ” 将方法名和对象或类的名字分隔开来。

如下三种主要使用情况 :

  • 对象 :: 实例方法
  • 类 :: 静态方法
  • 类 :: 实例方法

可以将方法引用理解为 Lambda 表达式的另外一种表现形式,方法引用所引用的方法的参数列表与返回值类型,需要与函数式接口中抽象方法的参数列表和返回值类型保持一致!

2.1 对象 :: 实例方法

    @Test
    public void test1() {
        Consumer<String> con1 = (str) -> System.out.println(str);
        con1.accept("Hello World!!!");

        PrintStream ps = System.out;
        Consumer<String> con2 = ps::println;
        con2.accept("Hello Java8!!!");

        Consumer<String> con3 = System.out::println;
        con3.accept("Hello Lambda!!!");
    }

    @Test
    public void test2() {
        Employee emp = new Employee();
        emp.setName("张起灵");
        emp.setAge(18);

        Supplier<? extends Object> sup1 = () -> emp.getName();
        String str = (String) sup1.get();
        System.out.println(str);

        Supplier<Integer> sup2 = emp::getAge;
        Integer age = sup2.get();
        System.out.println(age);
    }
package com.szh.java8;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 *
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {

    private Integer id;
    private String name;
    private Integer age;
    private Double salary;

    public Employee(Integer id) {
        this.id = id;
    }

    public Employee(Integer id,String name) {
        this.id = id;
        this.name = name;
    }

}

2.2 类 :: 静态方法

    @Test
    public void test3() {
        Comparator<Integer> com1 = (x,y) -> Integer.compare(x,y);
        System.out.println(com1.compare(10, 20));

        Comparator<Integer> com2 = Integer::compare;
        System.out.println(com2.compare(300, 110));
    }

2.3 类 :: 实例方法

若 Lambda 的参数列表的第一个参数是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,格式: ClassName::MethodName

    @Test
    public void test4() {
        BiPredicate<String,String> bp1 = (str1,str2) -> str1.equals(str2);
        System.out.println(bp1.test("Hello", "hello"));

        BiPredicate<String,String> bp2 = String::equals;
        System.out.println(bp2.test("Java", "Java"));
    }

3.构造器引用

格式 : ClassName::new

与函数式接口相结合,自动与函数式接口中方法兼容。构造器的参数列表,需要与函数式接口中参数列表保持一致!

代码中Employee类参考上面的案例。

    @Test
    public void test5() {
        //无参构造器
        Supplier<Employee> sup1 = () -> new Employee();
        System.out.println(sup1.get());

        //无参构造器
        Supplier<Employee> sup2 = Employee::new;
        System.out.println(sup2.get());

        //一个参数构造器
        Function<Integer,Employee> function = Employee::new;
        Employee employee = function.apply(1001);
        System.out.println(employee);

        //两个参数构造器
        BiFunction<Integer,String,Employee> biFunction = Employee::new;
        Employee emp = biFunction.apply(1001, "张起灵");
        System.out.println(emp);
    }

4.数组引用

格式 :类型[] :: new

    @Test
    public void test6() {
        Function<Integer,String[]> fun = (x) -> new String[x];
        String[] strings = fun.apply(10);
        System.out.println(strings.length);

        Function<Integer,String[]> fun2 = String[]::new;
        String[] strArray = fun2.apply(50);
        System.out.println(strArray.length);
    }

以上就是深入浅出理解Java Lambda表达式之四大核心函数式的用法与范例的详细内容,更多关于Java Lambda表达式的资料请关注我们其它相关文章!

(0)

相关推荐

  • 深入理解Java8新特性之Lambda表达式的基本语法和自定义函数式接口

    1.写在前面 目前我们学习Java主要用到的应该就是Java8了,或者说大部分企业当前使用的也是Java8.那么既然Java8的应用如此之广泛,一定有一些亮点所在: Lambda 表达式 函数式接口 方法引用与构造器引用 Stream API 接口中的默认方法与静态方法 新时间日期API 其他新特性 速度更快.代码更少(增加了新的语法 Lambda 表达式).强大的 Stream API.便于并行.最大化减少空指针异常 Optional. 2.为什么要使用Lambda表达式? Lambda 是一

  • java Lambda表达式的使用心得

    目录 Lambda表达式的心得 Lambda表达式法 传统方法 使用Lambda表达式 你首先要知道的 Lambda表达式的技巧 Lambda表达式只能用来简化仅包含一个public方法的接口的创建 双冒号表达形式 Lambda表达式的心得 如题,因为博主也是最近才接触到Lambda表达式的(PS 在这里汗颜一会).我并不会讲解它的原理,诚然任何一件事物如果理解原理的话,使用它必将更加容易.但博主在学习的时候,大多数时候都是学会怎么用,然后在细究原理.就像你骑自行车之前,难道首先还要研究自行车的

  • Java中Lambda表达式的使用详解

    目录 理解函数式接口以及 Lambda表达式的发展过程 Lambda表达式及语法 一起来看看具体的使用 你需要注意什么 Lambda的实际运用 1.对集合排序 2.遍历集合 3.遍历集合(带条件) 4.代替 Runnable,开启一个线程 理解函数式接口以及 Lambda表达式的发展过程 任何接口,只包含唯一一个抽象方法,就是函数式接口 /** * lambdab表达式的发展 */ public class TestLambda1 { //3.静态内部类 static class Like2 i

  • 一文带你掌握Java8中Lambda表达式 函数式接口及方法构造器数组的引用

    目录 函数式接口概述 函数式接口示例 1.Runnable接口 2.自定义函数式接口 3.作为参数传递 Lambda 表达式 内置函数式接口 Lambda简述 Lambda语法 方法引用 构造器引用 数组引用 函数式接口概述 只包含一个抽象方法的接口,称为函数式接口. 可以通过 Lambda 表达式来创建该接口的对象. 可以在一个接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口.同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口.

  • Java中Lambda表达式的进化之路详解

    目录 Lambda表达式的进化之路 为什么要使用Lambda表达式 Lambda表达式的注意点 下面是Lambda表达式的实现过程 1.最开始使用的是定义外部实现类来完成接口 2.开始使用静态内部类来实现 3.使用局部内部类使用 4.使用匿名内部类实现接口 5..最后使用Lambda表达式实现函数式接口 总结 Lambda表达式的进化之路 为什么要使用Lambda表达式 可以简洁代码,提高代码的可读性 可以避免匿名内部类定义过多导致逻辑紊乱 在原先实现接口抽象方法的时候,需要通过定义一个实现接口

  • Java中使用Lambda表达式和函数编程示例

    目录 1.简单介绍 2.Lambdas和Scopes 3.Lambdas与局部变量 4.Lambda体与局部变量 5.Lambdas和'This'和'Super'关键字 6.Lambdas和Exceptions 7.预定义的功能接口 1.简单介绍 第一个示例演示变量声明上下文中的lambda.它将lambda()->{System.out.println("running"):}分配给可运行接口类型的变量r. 第二个示例类似,但演示了赋值上下文中的lambda(到先前声明的变量r

  • Java中forEach使用lambda表达式,数组和集合的区别说明

    1.数组怎么使用lambda 数组不能直接在forEach中使用lambda表达式 PartnerType[] values = PartnerType.values(); //提示Cannot resolve method 'forEach(<method reference>) values.forEach(System.out::println);//错误使用 想要使用必须转换,如下 (1)转成list (2)转成steam PartnerType[] values = PartnerT

  • Java 进阶使用 Lambda 表达式实现超强的排序功能

    目录 基于Comparator排序 使用 Lambda 表达式替换Comparator匿名内部类 通过静态方法抽取公共的 Lambda 表达式 借助Comparator的comparing方法 多条件排序 在Stream中进行排序 倒序排列 调转排序判断 在Comparator.comparing中定义排序反转 在Stream中定义排序反转 null 值的判断 元素是 null 的笨拙实现 排序条件的字段是 null 文末总结 我们在系统开发过程中,对数据排序是很常见的场景.一般来说,我们可以采

  • Java Lambda 表达式源码解析

    Java Lambda 源码分析 问题: Lambda 表达式是什么?JVM 内部究竟是如何实现 Lambda 表达式的?为什么要这样实现? 一.基本概念 1.Lambda 表达式 下面的例子中,() -> System.out.println("1") 就是一个 Lambda 表达式.Java 8 中每一个 Lambda 表达式必须有一个函数式接口与之对应.Lambda 表达式就是函数式接口的一个实现. @Test public void test0() { Runnable

  • 关于Java 中的 Lambda 表达式

    这篇文章我们将讨论关于Java 中的 Lambda 表达式,Lambda 表达式是 Java 涉足函数式编程的过程.它接受参数并将其应用于表达式或代码块.以下是语法的基本示例: (parameter1, parameter2) => expression 或者 (parameter1, parameter2) => {code block} Lambda 表达式非常有限,如果它不是 void,则必须立即返回一个值.他们不能使用诸如 if 或 for 之类的关键字来保持简单性.如果需要更多行代码

随机推荐