1. Lambda表达式
1.1 Lambda使用场景
Lambda表达式是java8引入的新特性,直接点说,就是新的一种java语法,是每一个java程序猿必须掌握的技能。它的使用场景是,当我需要实现一个被@FunctionalInterface注解修饰的接口时,我们就可以使用Lambda表达式。比如我们需要一个实现了Runnable接口的类,或需要一个实现了Comparator接口的类,再或者我们自定义了一个接口(接口被@FunctionalInterface注解),当我们需要这个接口的实现类的时候,也可以直接使用lambda表达式。
@FunctionalInterface注解的作用是,告诉jvm,这个接口是只包含一个方法的接口。所以,我们编写的lambda表达式就是对这个接口仅有的一个方法的实现!只要被这个注解修饰的接口,我们就称它为函数式接口。从目前的经验看,lambda表达式实现这个接口方法的时候,是无法像一个正常的接口实现类那样还能新增实现类的属性,或者新增其他方法等。如果想让实现类具备自己的属性,或者定义其他方法,那还是按照原来的写法,去实现这个接口吧。
-
@FunctionalInterface
-
public
interface Runnable {
-
-
public abstract void run();
-
}
使用Lambda创建一个Runnable的实现类,来执行一个线程,代码如下
-
public void test1(){
-
//jdk 1.7 前,必须是 final
-
int num =
0;
-
// 使用匿名内部类的方式
-
Runnable r =
new Runnable() {
-
@Override
-
public void run() {
-
System.out.println(
"Hello World!" + num);
-
}
-
};
-
r.run();
-
System.out.println(
"分割线-------------------------------");
-
// 使用lambda 一行代码实现Runnable接口的run方法
-
Runnable r1 = () -> System.out.println(
"Hello Lambda!");
-
r1.run();
-
}
1.2 Lambda基础语法
Lambda 表达式的基础语法:Java8中引入了一个新的操作符 "->" 该操作符称为箭头操作符或 Lambda 操作符:箭头操作符将 Lambda 表达式拆分成两部分:
左侧:Lambda 表达式的参数列表
右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体
- 语法格式一:实现的接口方法无参数,无返回值
Runnable r1 = () -> System.out.println("Hello Lambda!");
- 语法格式二:实现的接口方法有一个参数,并且无返回值
(x) -> System.out.println(x); //x是随便起的名字,想叫什么都行
- 语法格式三:实现的接口方法若只有一个参数,小括号可以省略不写
x -> System.out.println(x)
- 语法格式四:实现的接口方法有两个以上的参数,有返回值,并且 Lambda 体中有多条语句
Comparator<Integer> com = (x, y) -> {
System.out.println("函数式接口");
return Integer.compare(x, y);
};
// lambda表达式需要多条语句,那就用{},有返回值则最后使用return
- 语法格式五:若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写
Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
- 语法格式六:Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断”
(Integer x, Integer y) -> Integer.compare(x, y);
通过上面的语法总结,只要我们需要一个函数式接口的实现类的简单实现时,就可以直接使用lambda表达式,来表示这个实现类。
1.3 Java8 内置的四大核心函数式接口
通过上面的学习,我们知道写lambda之前必须先有一个函数式接口,那么java8就为我们提供了四大核心函数式接口。
- Consumer<T> : 消费型接口 void accept(T t);
- Supplier<T> : 供给型接口 T get();
- Function<T, R> : 函数型接口 R apply(T t);
- Predicate<T> : 断言型接口 boolean test(T t);
-
package com.wqh.demo.java8;
-
-
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;
-
-
import org.junit.Test;
-
-
/*
-
* Java8 内置的四大核心函数式接口
-
*
-
* Consumer<T> : 消费型接口
-
* void accept(T t);
-
*
-
* Supplier<T> : 供给型接口
-
* T get();
-
*
-
* Function<T, R> : 函数型接口
-
* R apply(T t);
-
*
-
* Predicate<T> : 断言型接口
-
* boolean test(T t);
-
*
-
*/
-
public
class TestLambda3 {
-
-
//Predicate<T> 断言型接口:
-
@Test
-
public void test4(){
-
List<String> list = Arrays.asList(
"Hello",
"atguigu",
"Lambda",
"www",
"ok");
-
List<String> strList = filterStr(list, (s) -> s.length() >
3);
-
-
for (String str : strList) {
-
System.out.println(str);
-
}
-
}
-
-
//需求:将满足条件的字符串,放入集合中
-
public List<String> filterStr(List<String> list, Predicate<String> pre){
-
List<String> strList =
new ArrayList<>();
-
-
for (String str : list) {
-
if(pre.test(str)){
-
strList.add(str);
-
}
-
}
-
-
return strList;
-
}
-
-
//Function<T, R> 函数型接口:
-
@Test
-
public void test3(){
-
String newStr = strHandler(
"\t\t\t 我大中华威武 ", (str) -> str.trim());
-
System.out.println(newStr);
-
-
String subStr = strHandler(
"我大中华威武", (str) -> str.substring(
2,
5));
-
System.out.println(subStr);
-
}
-
-
//需求:用于处理字符串
-
public String strHandler(String str, Function<String, String> fun){
-
return fun.apply(str);
-
}
-
-
//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> sup){
-
List<Integer> list =
new ArrayList<>();
-
-
for (
int i =
0; i < num; i++) {
-
Integer n = sup.get();
-
list.add(n);
-
}
-
-
return list;
-
}
-
-
//Consumer<T> 消费型接口 :
-
@Test
-
public void test1(){
-
happy(
10000, (m) -> System.out.println(
"你们刚哥喜欢大宝剑,每次消费:" + m +
"元"));
-
}
-
-
public void happy(double money, Consumer<Double> con){
-
con.accept(money);
-
}
-
}
1.4 Lambda方法引用
一、方法引用:若 Lambda 体中的功能,已经有方法提供了实现,可以使用方法引用(可以将方法引用理解为 Lambda 表达式的另外一种表现形式)
1. 对象的引用 :: 实例方法名
2. 类名 :: 静态方法名
3. 类名 :: 实例方法名
注意:
①方法引用所引用的方法的参数列表与返回值类型,需要与函数式接口中抽象方法的参数列表和返回值类型保持一致!
②若Lambda 的参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,格式: ClassName::MethodName
-
//对象的引用 :: 实例方法名
-
@Test
-
public void test2(){
-
Employee emp =
new Employee(
101,
"张三",
18,
9999.99);
-
-
Supplier<String> sup = () -> emp.getName();
-
System.out.println(sup.get());
-
-
System.out.println(
"----------------------------------");
-
// getName方法与Supplier接口的get方法,入参相同、返回值类型相同
-
Supplier<String> sup2 = emp::getName;
-
System.out.println(sup2.get());
-
}
-
-
//类名 :: 静态方法名
-
@Test
-
public void test3(){
-
BiFunction<Double, Double, Double> fun = (x, y) -> Math.max(x, y);
-
System.out.println(fun.apply(
1.5,
22.2));
-
-
System.out.println(
"--------------------------------------------------");
-
// BiFunction的apply方法,同Math的max方法,入参类型相同,返回值类型相同,可以直接忽略的参数列表
-
BiFunction<Double, Double, Double> fun2 = Math::max;
-
System.out.println(fun2.apply(
1.2,
1.5));
-
}
-
-
//类名 :: 实例方法名
-
@Test
-
public void test5(){
-
// BiPredicate接口的boolean test(T t, U u)方法
-
BiPredicate<String, String> bp = (x, y) -> x.equals(y);
-
System.out.println(bp.test(
"abcde",
"abcde"));
-
System.out.println(
"-----------------------------------------");
-
// 使用第一个参数调用equals方法,将第二个参数作为equals的入参
-
BiPredicate<String, String> bp2 = String::equals;
-
System.out.println(bp2.test(
"abc",
"abc"));
-
-
System.out.println(
"-----------------------------------------");
-
-
// Function接口的R apply(T t)方法
-
Function<Employee, String> fun = (e) -> e.show();
-
System.out.println(fun.apply(
new Employee()));
-
-
System.out.println(
"-----------------------------------------");
-
// 使用第一个参数一个Employee对象调用show方法
-
Function<Employee, String> fun2 = Employee::show;
-
System.out.println(fun2.apply(
new Employee()));
-
-
}
-
-
//类名 :: 实例方法名
-
@Test
-
public void test5(){
-
// BiPredicate接口的boolean test(T t, U u)方法
-
BiPredicate<String, String> bp = (x, y) -> x.equals(y);
-
System.out.println(bp.test(
"abcde",
"abcde"));
-
System.out.println(
"-----------------------------------------");
-
// 使用第一个参数调用equals方法,将第二个参数作为equals的入参
-
BiPredicate<String, String> bp2 = String::equals;
-
System.out.println(bp2.test(
"abc",
"abc"));
-
-
System.out.println(
"-----------------------------------------");
-
-
// Function接口的R apply(T t)方法
-
Function<Employee, String> fun = (e) -> e.show();
-
System.out.println(fun.apply(
new Employee()));
-
-
System.out.println(
"-----------------------------------------");
-
// 使用第一个参数一个Employee对象调用show方法
-
Function<Employee, String> fun2 = Employee::show;
-
System.out.println(fun2.apply(
new Employee()));
-
-
}
二、构造器引用 :构造器的参数列表,需要与函数式接口中参数列表保持一致!
1. 类名 :: new
2. 数组引用 类型[] :: new;
-
@Test
-
public void test6(){
-
//Supplier接口的T get();方法
-
Supplier<Employee> sup = () ->
new Employee();
-
System.out.println(sup.get());
-
-
System.out.println(
"------------------------------------");
-
//自动匹配Employee的无参构造器
-
Supplier<Employee> sup2 = Employee::
new;
-
System.out.println(sup2.get());
-
//BiFunction的R apply(T t, U u);方法,自动匹配参数类型是String, Integer的构造器
-
BiFunction<String, Integer, Employee> fun2 = Employee::
new;
-
System.out.println(fun2.apply(
"小明",
28));
-
}
-
//数组引用
-
@Test
-
public void test8(){
-
Function<Integer, String[]> fun = (args) ->
new String[args];
-
String[] strs = fun.apply(
10);
-
System.out.println(strs.length);
-
-
System.out.println(
"--------------------------");
-
-
Function<Integer, Employee[]> fun2 = Employee[] ::
new;
-
Employee[] emps = fun2.apply(
20);
-
System.out.println(emps.length);
-
}
-
package com.wqh.demo.java8;
-
-
public
class Employee {
-
-
private
int id;
-
private String name;
-
private
int age;
-
private
double salary;
-
private Status status;
-
-
public Employee() {
-
}
-
-
public Employee(String name) {
-
this.name = name;
-
}
-
-
public Employee(String name, int age) {
-
this.name = name;
-
this.age = age;
-
}
-
-
public Employee(int id, String name, int age, double salary) {
-
this.id = id;
-
this.name = name;
-
this.age = age;
-
this.salary = salary;
-
}
-
-
public Employee(int id, String name, int age, double salary, Status status) {
-
this.id = id;
-
this.name = name;
-
this.age = age;
-
this.salary = salary;
-
this.status = status;
-
}
-
-
public Status getStatus() {
-
return status;
-
}
-
-
public void setStatus(Status status) {
-
this.status = status;
-
}
-
-
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 String show() {
-
return
"测试方法引用!";
-
}
-
-
@Override
-
public int hashCode() {
-
final
int prime =
31;
-
int result =
1;
-
result = prime * result + age;
-
result = prime * result + id;
-
result = prime * result + ((name ==
null) ?
0 : name.hashCode());
-
long temp;
-
temp = Double.doubleToLongBits(salary);
-
result = prime * result + (
int) (temp ^ (temp >>>
32));
-
return result;
-
}
-
-
@Override
-
public boolean equals(Object obj) {
-
if (
this == obj)
-
return
true;
-
if (obj ==
null)
-
return
false;
-
if (getClass() != obj.getClass())
-
return
false;
-
Employee other = (Employee) obj;
-
if (age != other.age)
-
return
false;
-
if (id != other.id)
-
return
false;
-
if (name ==
null) {
-
if (other.name !=
null)
-
return
false;
-
}
else
if (!name.equals(other.name))
-
return
false;
-
if (Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary))
-
return
false;
-
return
true;
-
}
-
-
@Override
-
public String toString() {
-
return
"Employee [id=" + id +
", name=" + name +
", age=" + age +
", salary=" + salary +
", status=" + status
-
+
"]";
-
}
-
-
public
enum Status {
-
FREE, BUSY, VOCATION;
-
}
-
-
}
转载:https://blog.csdn.net/u010327957/article/details/104777717