Java8 Lambda表达式
Lambda表达式简介
- Lambda表达式是Java 8的新特性,是一个函数式接口。
- 使用Lamda表达式可以对一个接口进行十分简单的实现。
Lambda对接口的要求:
Lambda要求接口中定义的必须实现的抽象方法只能是一个。
@FunctionInterface
用来修饰函数式接口,接口中的抽象方法只能有一个。
Lambda基础语法
因为Lambda 是一个匿名函数,所以只需要关注返回值类型、参数列表和方法体,不需要关注方法名,并且在Lambda中返回值类型不需要显式的表示出来。
():用来描述参数列表
{}:用来描述方法体
->:Lambda运算符,读作:goes to
自定义函数式接口
无参无返回值
/**
* @author leizige
*/
@FunctionalInterface
public interface Math {
void add();
}
class test {
public static void main(String[] args) {
Math math = () -> {
System.out.println("无参无返回...");
};
math.add();
}
}
无参有一个参数
/**
* @author leizige
*/
@FunctionalInterface
public interface Math {
void add(int a);
}
class test {
public static void main(String[] args) {
Math math = (a) -> {
System.out.println("无返回值,有一个参数..." + a);
};
math.add(666);
}
}
无参有多个参数
/**
* @author leizige
*/
@FunctionalInterface
public interface Math {
void add(int a, int b, int c);
}
class test {
public static void main(String[] args) {
Math math = (a, b, c) -> {
System.out.println("无返回值,有多个参数..." + (a + b + c));
};
math.add(1, 2, 3);
}
}
有返回值,无参数
/**
* @author leizige
*/
@FunctionalInterface
public interface Math {
int add();
}
class test {
public static void main(String[] args) {
Math math = () -> {
return 0;
};
int result = math.add();
System.err.println(result);
}
}
有返回值,有一个参数
/**
* @author leizige
*/
@FunctionalInterface
public interface Math {
int add(int a);
}
class test {
public static void main(String[] args) {
Math math = (a) -> {
return a;
};
int result = math.add(1);
System.err.println(result);
}
}
有返回值,有多个参数
/**
* @author leizige
*/
@FunctionalInterface
public interface Math {
int add(int a, int b);
}
class test {
public static void main(String[] args) {
Math math = (int a, int b) -> {
return a + b;
};
int result = math.add(1, 2);
System.err.println(result);
}
}
Lambda表达式语法精简
-
参数
由于再接口的抽象方法中,已经定义了参数的数量和类型,所以在Lambda中参数的类型可以省略。
注意:如果需要省参数类型,则每一个参数的类型都要省略;
-
参数小括号
如果参数列表中,参数的数量只有一个,此时小括号可以省略。
-
方法大括号
如果方法体中只有一条语句,大括号可以省略。
-
return
如果方法体中唯一的一条语句是一个返回语句,则在省略掉大括号的同时,需要把return去掉。
省略参数类型
Math math = (a,b)->{
System.out.println();
};
省略参数小括号
Math math = a -> {
System.out.println(a);
};
省略方法大括号
Math math = a -> System.out.println(a);
省略 return 语句
Math math = () -> 10;
Lambda表达式方法引用
方法引用:
- 可以快速的将一个Lambda表达式的实现指向一个已经实现的方法。
- 语法:
方法的隶属者::方法名
。
注意:
- 参数的数量和类型一定要和接口中定义的方法一致。
- 返回值的类型一定要和接口中定义的方法一致。
@Data
@ToString
/* 为Student类生成无参和有参构造*/
@NoArgsConstructor
@AllArgsConstructor
class Student {
private String name;
private Integer age;
}
@FunctionalInterface
interface StudentOne {
Student getStudent();
}
@FunctionalInterface
interface StudentTwo {
Student getStudent(String name, Integer age);
}
class test {
public static void main(String[] args) {
StudentOne s1 = Student::new;
//无参构造方法引用
StudentOne s2 = Student::new;
Student result1 = s2.getStudent();
System.err.println(result1);
//有参构造方法引用
StudentTwo p3 = Student::new;
Student result2 = p3.getStudent("zs", 23);
System.err.println(result2);
}
}
内置函数接口使用
核心内置函数接口介绍
函数式接口 | 参数类型 | 返回类型 | 函数式接口 | 用途 |
---|---|---|---|---|
Consumer | T | void | void accept(T t); | 对T类型参数操作,无返回结果。 |
supplier | 无 | T | T get(); | 返回T类型参数。 |
Function | T | R | R apply(T t); | 对类型T参数操作,返回R类型参数。 |
Predicate | T | boolean | boolean test(T t); | 断言型接口,对类型T进行条件筛选。 |
四大核心函数式接口
Consumer 消费型接口
void accept(T t);
import java.math.BigDecimal;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
/**
* @author leizige
*/
public class ConsumerTest {
public static void main(String[] args) {
/* Consumer<T> 消费型接口 */
shopping1(BigDecimal.valueOf(1000), money -> System.err.println("消费金额¥" + money));
shopping2(2000, money -> System.err.println("消费金额¥" + money));
}
public static void shopping1(BigDecimal money, Consumer<BigDecimal> consumer) {
consumer.accept(money);
}
public static void shopping2(int money, IntConsumer consumer) {
consumer.accept(money);
}
}
除了上面使用的 Consumer 和 IntConsumer 之外,还可以使用 LongConsumer、DoubleConsumer
等,使用方法和上面一样。
Supplier 供给型接口
T get();
import lombok.ToString;
import java.util.Random;
import java.util.function.Supplier;
/**
* @author leizige
*/
public class SupplierTest {
public static void main(String[] args) {
/* Supplier<T> 供给型接口 */
Integer random = random(() -> new Random().nextInt());
System.err.println("random :" + random);
Person person = (Person) create(Person::new);
System.err.println("person : " + person);
}
public static <T> T random(Supplier<T> supplier) {
return supplier.get();
}
public static Object create(Supplier<?> supplier) {
return supplier.get();
}
}
@ToString
class Person {
private String name;
private String age;
}
除了上面使用的 Supplier 接口,还可以使用 IntSupplier 、DoubleSupplier 、LongSupplier 、BooleanSupplier
等,使用方法和上面一样。
Function<T, R> 函数式接口
R apply(T t);
/**
* @author leizige
*/
public class FunctionTest {
public static void main(String[] args) {
String newStr = convert("oldStr", (oldStr) -> oldStr.toUpperCase());
System.err.println(newStr);
Integer length = length("HelloWorld", String::length);
System.err.println("HelloWorld length : " + length);
}
/**
* function的作用是转换,将一个值转为另外一个值
*
* @param oldStr oldStr
* @param function Function
* @return newStr
*/
public static String convert(String oldStr, Function<String, String> function) {
return function.apply(oldStr);
}
/**
* 泛型的第一个参数是转换前的类型,第二个是转化后的类型
*/
public static Integer length(String str, Function<String, Integer> function) {
return function.apply(str);
}
}
Predicate 函数式接口
boolean test(T t);
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import java.util.function.Predicate;
import java.util.stream.Stream;
/**
* @author leizige
*/
public class PredicateTest {
public static void main(String[] args) {
Predicate<Integer> result1 = num -> num < 10;
System.err.println(result1.test(9));
compareString();
compareObject();
filterNumber();
}
/**
* 比较字符串
*/
public static void compareString() {
String a = "666";
String b = "666";
Predicate<String> result = v -> v.equals(b);
System.err.println(result.test(a));
}
/**
* 比较对象
*/
public static void compareObject() {
Student stu1 = new Student();
Student stu2 = new Student("zs", 23);
Predicate<Student> result1 = v -> v == stu2;
System.out.println(result1.test(stu1));
Student stu3 = stu2;
Predicate<Student> result2 = v -> v == stu2;
System.out.println(result2.test(stu3));
}
/**
* 过滤
*/
public static void filterNumber() {
Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
Predicate<Integer> predicate = num -> num >= 6;
numbers.filter(predicate).forEach(System.err::print);
}
}
@NoArgsConstructor
@AllArgsConstructor
class Student {
private String name;
private Integer age;
}
If you’re going to reuse code, you need to understand that code!