lambda表达式

lambda表达式

本质:函数式接口的实例。

1 lambda表达式的使用

格式

  • lambda表达式分为三部分:形参列表 箭头操作符 lambda体。例子:
(a, b) -> Integer.compare(a, b);
形参列表  箭头操作符  lambda体
  • 形参列表:其实就是接口中的抽象方法的形参列表。

  • lambda体:其实就是重写的抽象方法的方法体。

语法格式一:无参,无返回值

@Test
public void test1() {
    Runnable r1 = new Runnable() {
        @Override
        public void run() {
            System.out.println("hello");
        }
    };
    r1.run();  // 就是普通的函数调用

    System.out.println("-------------------------");

    Runnable r2 = () -> System.out.println("world");
    r2.run();
}

语法格式二:一个参数,无返回值

@Test
public void test2() {
    Consumer<String> con1 = new Consumer<String>() {
        @Override
        public void accept(String s) {
            System.out.println(s);
        }
    };
    con1.accept("hello");

    System.out.println("-------------------------");

    Consumer<String> con2 = s -> System.out.println(s);  // 类型推断
    con2.accept("world");
}

语法格式三:两个或以上的参数,多条执行语句,可以有返回值

@Test
public void test3() {
    Comparator<Integer> com1 = new Comparator<Integer>() {
        @Override
        public int compare(Integer a, Integer b) {
            System.out.println(a);
            System.out.println(b);
            return a.compareTo(b);
        }
    };
    System.out.println(com1.compare(1, 2));

    System.out.println("-------------------------");

    Comparator<Integer> com2 = (a, b) -> {
        System.out.println(a);
        System.out.println(b);
        return a.compareTo(b);
    };
    System.out.println(com2.compare(2, 1));
}

语法格式四:当lambda体只有一条语句时,可以省略大括号和return

@Test
public void test4() {
    Comparator<Integer> com1 = new Comparator<Integer>() {
        @Override
        public int compare(Integer a, Integer b) {
            return a.compareTo(b);
        }
    };
    System.out.println(com1.compare(1, 2));

    System.out.println("-------------------------");

    Comparator<Integer> com2 = (a, b) ->  a.compareTo(b);
    System.out.println(com2.compare(2, 1));
}

2 函数式接口

函数式接口:如果一个接口中,只声明了一个抽象方法,则此接口就被称为函数式接口。

  • 我们可以在一个接口上使用@FunctionalInterface注解,这样做可以检查它是否是一个函数式接口。

  • lambda表达式 和 函数式接口 的关系:lambda表达式依赖于函数式接口,如果函数式接口不存在,那么也不可能存在lambda表达式。lambda表达式本质上是函数式接口的实例

Java内置四大核心函数式接口

函数式接口参数类型返回类型用途
Consumer<T>Tvoid消费型接口。包含的方法:void accept(T t)
Supplier<T>T供给型接口。包含的方法:T get()
Function<T, R>TR函数型接口。包含的方法:R apply(T t)
Predicate<T>Tboolean断定型接口。包含的方法:boolean test(T t)

使用举例

// 消费型接口
@Test
public void test1() {
    enjoy(500, new Consumer<Double>() {
        @Override
        public void accept(Double money) {
            System.out.println("消费了" + money + "元...");
        }
    });

    System.out.println("-------------------------");

    enjoy(400, money -> System.out.println("消费了" + money + "元..."));
}

public void enjoy(double money, Consumer<Double> con) {
    con.accept(money);
}
// 断定型接口
@Test
public void test2() {
    List<String> list = Arrays.asList("北京", "南京", "天津", "东京");
    List<String> res1 = filterString(list, new Predicate<String>() {
        @Override
        public boolean test(String s) {
            return s.contains("京");  // 判定规则:字符串中是否含有 京
        }
    });
    System.out.println(res1);

    System.out.println("-------------------------");

    List<String> res2 = filterString(list, s -> s.contains("京"));
    System.out.println(res2);
}

public List<String> filterString(List<String> list, Predicate<String> pre) {
    List<String> res = new ArrayList<>();
    for (String s : list)
        if (pre.test(s))  // 判定是否成功
            res.add(s);
    return res;
}

3 方法引用

方法引用:就是lambda表达式,只不过形式不同。

  • 当要传递给lambda体的操作,已经有实现的方法了,可以使用方法引用。

  • 要求:实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致。

  • 格式:使用操作符 :: 将类(对象) 与 方法名 分割开来。

  • 有如下三种使用情况:

    • (1)对象 :: 实例方法

    • (2)类 :: 静态方法

    • (3)类 :: 实例方法

关于Empoyee类请参考附录

情况一:对象 :: 实例方法

// 情况一:对象 :: 实例方法
// Consumer中的void accept(T t)
// PrintStream中的void println(T t)
@Test
public void test1() {
    Consumer<String> con1 = s -> System.out.println(s);
    con1.accept("北京");

    System.out.println("-------------------------");

    Consumer<String> con2 = System.out::println;  // 方法引用
    con2.accept("beijing");
}

// Supplier中的T get()
// Employee中的String getName()
@Test
public void test2() {
    Employee emp = new Employee(1001, "Tom", 23, 5600);

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

    System.out.println("-------------------------");

    Supplier<String> sup2 = emp::getName;
    System.out.println(sup2.get());
}

情况二:类 :: 静态方法

// 情况二:类 :: 静态方法
// Comparator中的int compare(T t1,T t2)
// Integer中的int compare(T t1,T t2)
@Test
public void test3() {
    Comparator<Integer> com1 = (a, b) -> Integer.compare(a, b);
    System.out.println(com1.compare(1, 2));

    System.out.println("-------------------------");

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

// Function中的R apply(T t)
// Math中的Long round(Double d)
@Test
public void test4() {
    Function<Double, Long> func = new Function<Double, Long>() {
        @Override
        public Long apply(Double d) {
            return Math.round(d);
        }
    };
    Function<Double, Long> func1 = d -> Math.round(d);
    System.out.println(func1.apply(12.3));

    System.out.println("-------------------------");

    Function<Double, Long> func2 = Math::round;
    System.out.println(func2.apply(12.6));
}

情况三:类 :: 实例方法

// 情况三:类 :: 实例方法
// Comparator中的int comapre(T t1,T t2)
// String中的int t1.compareTo(t2)
@Test
public void test5() {
    Comparator<String> com1 = (a, b) -> a.compareTo(b);
    System.out.println(com1.compare("abc", "abf"));

    System.out.println("-------------------------");

    Comparator<String> com2 = String::compareTo;
    System.out.println(com2.compare("abc", "abm"));
}

// BiPredicate中的boolean test(T t1, T t2);
// String中的boolean t1.equals(t2)
@Test
public void test6() {
    BiPredicate<String, String> pre1 = (a, b) -> a.equals(b);
    System.out.println(pre1.test("abc", "abc"));

    System.out.println("-------------------------");

    BiPredicate<String, String> pre2 = String::equals;
    System.out.println(pre2.test("abc", "abd"));
}

// Function中的R apply(T t)
// Employee中的String getName();
@Test
public void test7() {
    Employee emp = new Employee(1001, "Jerry", 23, 6000);

    Function<Employee, String> func1 = e -> e.getName();
    System.out.println(func1.apply(emp));

    System.out.println("-------------------------");

    Function<Employee, String> func2 = Employee::getName;
    System.out.println(func2.apply(emp));
}

4 构造器引用

// 构造器引用
// Supplier中的T get()
// 调用无参的构造器
@Test
public void test1() {
    Supplier<Employee> sup = new Supplier<Employee>() {
        @Override
        public Employee get() {
            return new Employee();
        }
    };
    Supplier<Employee> sup1 = () -> new Employee();
    System.out.println(sup1.get());

    System.out.println("-------------------------");

    Supplier<Employee> sup2 = Employee::new;
    System.out.println(sup2.get());
}

// Function中的R apply(T t)
// 调用含有一个参数的构造器
@Test
public void test2() {
    Function<Integer, Employee> func1 = id -> new Employee(id);
    System.out.println(func1.apply(1001));

    System.out.println("-------------------------");

    Function<Integer, Employee> func2 = Employee::new;
    System.out.println(func2.apply(1002));
}

// BiFunction中的R apply(T t,U u)
// 调用含有两个参数的构造器
@Test
public void test3() {
    BiFunction<Integer, String, Employee> func1 = (id, name) -> new Employee(id, name);
    System.out.println(func1.apply(1001, "Tom"));

    System.out.println("-------------------------");

    BiFunction<Integer, String, Employee> func2 = Employee::new;
    System.out.println(func2.apply(1002, "Jerry"));
}

5 数组引用

// 数组引用: 可以把数组看做一个特殊的类,则写法与构造器一致
// Function中的R apply(T t)
@Test
public void test4() {
    Function<Integer, String[]> func1 = len -> new String[len];
    String[] arr1 = func1.apply(3);
    System.out.println(Arrays.toString(arr1));  // [null, null, null]

    System.out.println("-------------------------");

    Function<Integer, String[]> func2 = String[]::new;
    String[] arr2 = func2.apply(6);
    System.out.println(Arrays.toString(arr2));  // [null, null, null, null, null, null]
}

附录

public class Employee {

    private int id;
    private String name;
    private int age;
    private double salary;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public Employee() {

    }

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

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

    public Employee(int id, String name, int age, double salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Employee{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", salary=" + salary + '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Employee employee = (Employee) o;

        if (id != employee.id) return false;
        if (age != employee.age) return false;
        if (Double.compare(employee.salary, salary) != 0) return false;
        return name != null ? name.equals(employee.name) : employee.name == null;
    }

    @Override
    public int hashCode() {
        int result;
        long temp;
        result = id;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        result = 31 * result + age;
        temp = Double.doubleToLongBits(salary);
        result = 31 * result + (int) (temp ^ (temp >>> 32));
        return result;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值