Lambda表达式
标准格式
示例
new Thread(() -> {
System.out.println("多线程启动");
}).start();
//():里面没有内容,可以看做是方法形参为空
//->:用箭头指向后面要做的事情
//{}:包含一段代码,称之为代码块,可以看成是方法体中的内容
组成Lambda表达式三要素:形式参数+箭头+代码块
(形式参数) -> {代码块}
//形式参数:可以有多个,用逗号隔开,也可以没有,即留空
//箭头:代表指向动作
//代码块:具体要实现的动作
使用方法
1、需要有一个接口
2、在类中定义一个方法使用该接口
3、调用该方法,使用Lambda表达式简化书写
省略写法
- 参数类型可以省略(要么都写,要么都省略)
- 如果参数只有一个,参数小括号可以省略
- 如果代码块只有一行语句,代码块大括号可以省略,分号也可以省略
- 如果该行语句中有return,则return必须要省略
注意事项
- 接口中有且仅有一个抽象方法
- 必须有上下文环境,才能推导出Lanbda对应的接口
Lambda和匿名内部类区别
- Lambda表达式只能使用含有一个方法的接口,匿名内部类可以使用多方法接口、抽象类、具体类
- Lambda表达式不会产生新的字节码文件,匿名内部类会产生新的字节码文件
方法引用
方法引用符
::
该符号为方法引用符,它所在的表达式称为方法引用
示例
//Lambda表达式
usePrintable(s -> System.out.println(s));
//方法引用
usePrintable(System.out::println);
引用类方法
引用类的静态方法
类名 :: 静态方法
示例
//接口
public interface Converter {
int convert(String s);
}
//测试类
public class ConverterDemo {
public static void main(String[] args) {
//Lambda表达式
useConverter((String s)->{return Integer.parseInt(s);});//完整写法
useConverter(s->Integer.parseInt(s));//省略写法
//引用类方法
useConverter(Integer::parseInt);
}
private static void useConverter(Converter c){
int num=c.convert("897");
System.out.println(num);
}
}
引用对象实例方法
引用类中的成员方法
对象::成员方法
示例
//接口
public interface Printer {
void printUpperCase(String s);
}
//引用对象类
public class PrintString {
public void printUpper(String s){
System.out.println(s.toUpperCase());
}
}
//测试类
public class PrinterDemo {
public static void main(String[] args) {
//Lambda表达式
//标准写法
usePrinter((String s) -> {
System.out.println(s.toUpperCase());
});
//省略写法
usePrinter(s -> System.out.println(s.toUpperCase()));
//引用对象实例方法
PrintString printString = new PrintString();
usePrinter(printString::printUpper);
}
private static void usePrinter(Printer p) {
p.printUpperCase("abcdefg");
}
}
引用类的实例方法
应用类中的成员方法
类名::成员方法
示例
//接口
public interface MyString {
String mySubString(String s, int x, int y);
}
//测试类
public class MyStringDemo {
public static void main(String[] args) {
//Lambda表达式
useMyString((String s, int x, int y) -> {
return s.substring(x, y);
});
useMyString((s, x, y) -> s.substring(x, y));
//引用类的实例方法
//第一个参数作为调用者,后面的全部参数作为该方法的参数进行传递
useMyString(String::substring);
}
private static void useMyString(MyString m) {
String result = m.mySubString("abcdefghigklmn", 3, 6);
System.out.println(result);
}
}
引用构造器
引用构造方法
类名::new
示例
//接口
public interface StudentBuilder {
Student build(String name, int age);
}
//学生类
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
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 class StudentDemo {
public static void main(String[] args) {
//Lambda表达式
useStudentBuilder((String name, int age) -> {
return new Student(name, age);
});
useStudentBuilder((name, age) -> new Student(name, age));
//引用构造器
useStudentBuilder(Student::new);
}
private static void useStudentBuilder(StudentBuilder s) {
Student stu = s.build("刘晨旭", 27);
System.out.println(stu.getName() + ":" + stu.getAge());
}
}
函数式接口
概述
有且仅有一个抽象方法的接口,即可以适用Lambda表达式的接口
@FunctionalInterface//标识该接口为函数式接口
public interface MyInterface {
void show();
}
函数式接口作为方法的参数
示例
//接口
public interface Runnable {
public abstract void run();
//测试类
public class RunnableDemo {
public static void main(String[] args) {
//匿名内部类
startThread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程启动了");
}
});
//Lambda表达式
startThread(() -> System.out.println(Thread.currentThread().getName() + "线程启动了"));
}
private static void startThread(Runnable r) {
Thread thread = new Thread(r);
thread.start();
}
}
函数式接口作为方法返回值
可以使用Lambda表达式作为结果返回
示例
public class ComparatorDemo {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("aaaa");
arrayList.add("c");
arrayList.add("bbb");
System.out.println("排序前:" + arrayList);
Collections.sort(arrayList);
System.out.println("自然排序后:" + arrayList);
Collections.sort(arrayList, getComparator());
System.out.println("比较器排序后:" + arrayList);
}
private static Comparator<String> getComparator() {
//匿名内部类
// Comparator<String> com = new Comparator<String>() {
// @Override
// public int compare(String o1, String o2) {
// return o1.length()-o2.length();
// }
// };
// return com;
//Lambda表达式
return (String s1, String s2) -> {
return s1.length() - s2.length();
};
}
}
常用的函数式接口
Supplier接口
用于生产数据
Modifier and Type | 方法 | 描述 |
---|---|---|
T | get() | 获得结果。 |
public class SupplierDemo {
public static void main(String[] args) {
String s = getString(() -> "刘晨旭");
System.out.println(s);
int num = getInteger(() -> 27);
System.out.println(num);
}
private static String getString(Supplier<String> s) {
return s.get();
}
private static Integer getInteger(Supplier<Integer> s) {
return s.get();
}
}
Consumer接口
对参数进行操作
- 表示接受单个输入参数并且不返回结果的操作。 与大多数其他功能接口不同,
Consumer
预期通过副作用进行操作。
Modifier and Type | 方法 | 描述 |
---|---|---|
void | accept(T t) | 对给定的参数执行此操作。 |
default Consumer<T> | andThen(Consumer<? super T> after) | 返回一个组成的 Consumer ,依次执行此操作,然后执行 after 操作。 |
示例
public class ConsumerDemo {
public static void main(String[] args) {
operatorString("刘晨旭", s -> System.out.println(s));
operatorString("郭浩年", System.out::println);
operatorString("今天真是一个好日子", s -> System.out.println(s), s -> System.out.println(new StringBuilder(s).reverse().toString()));
}
private static void operatorString(String s, Consumer<String> con) {
con.accept(s);
}
private static void operatorString(String s, Consumer<String> con1, Consumer<String> con2) {
con1.andThen(con2).accept(s);
}
}
Predicate接口
对参数进行判断
-
表示一个参数的谓词(布尔值函数)。
这是一个functional interface,其功能方法是
test(Object)
。
Modifier and Type | 方法 | 描述 |
---|---|---|
default Predicate<T> | and(Predicate<? super T> other) | 返回一个组合的谓词,表示该谓词与另一个谓词的短路逻辑AND。 |
default Predicate<T> | negate() | 返回表示此谓词的逻辑否定的谓词。 |
default Predicate<T> | or(Predicate<? super T> other) | 返回一个组合的谓词,表示该谓词与另一个谓词的短路逻辑或。 |
boolean | test(T t) | 在给定的参数上评估这个谓词。 |
示例
public class PredicateDemo01 {
public static void main(String[] args) {
boolean b1 = check("acb", s -> s.length() > 5);
System.out.println(b1);
boolean b2 = check("abcdefg", s -> s.length() > 5, s -> s.length() < 15);
System.out.println(b2);
}
private static boolean check(String s, Predicate<String> pre) {
return pre.test(s);
//逻辑非
// return pre.negate().test(s);
}
private static boolean check(String s, Predicate<String> pre1, Predicate<String> pre2) {
//逻辑或
// return pre1.or(pre2).test(s);
//逻辑与
return pre1.and(pre2).test(s);
}
}
Function接口
-
表示接受一个参数并产生结果的函数。
这是一个functional interface的功能方法是
apply(Object)
。
Modifier and Type | 方法 | 描述 |
---|---|---|
default <V> Function<T,V> | andThen(Function<? super R,? extends V> after) | 返回一个组合函数,首先将该函数应用于其输入,然后将 after 函数应用于结果。 |
R | apply(T t) | 将此函数应用于给定的参数。 |
示例
public class FunctionDemo {
public static void main(String[] args) {
convert("456123",s->Integer.parseInt(s));
add(90,num->String.valueOf(num+10));
add("9999",Integer::parseInt,num->String.valueOf(num+1));
}
private static void convert(String s, Function<String,Integer> fun){
int num = fun.apply(s);
System.out.println(s);
}
private static void add(Integer num,Function<Integer,String> fun){
String str = fun.apply(num);
System.out.println(str);
}
private static void add(String s,Function<String,Integer> fun1,Function<Integer,String> fun2){
String str = fun1.andThen(fun2).apply(s);
System.out.println(str);
}
}