Lambda表达式
什么是Lambda表达式:
Lambda表达式是Java8的新特性之一,它是用来支持函数式编程,它是一个匿名内部类。使用Lambda表达式会让你的代码更加整洁。
函数式接口:
简单的说就是一个接口只有一个抽象方法;比如java.lang.Runnable和java.util.Comparator都是典型的函数式接口。可以使用注解 @FunctionalInterface来进行约束。
/**
* 函数式接口
*/
@FunctionalInterface
interface MyNum{
void print();
}
/**
* 函数式接口使用泛型
* @param <T>
*/
@FunctionalInterface
interface MyFunc<T> {
T getValue(T t);
}
Lambda 语法:
Lambda一般的语法是:(parameters) ->{method body};
(Parameters) | 方法的参数,可以不写参数类型,如果是一个参数的话,可以不用写() |
---|---|
-> | 用来分隔参数和主体 |
{} | 抽象方法的具体实现写在{}内,如果只有一条语句,可以不用写{} |
Ex:
/**
* 测试Lambda表达式
*/
public class Test {
public static void main(String[] args) {
MyNum myNum=()-> {
System.out.println("Hello");
};
myNum.print();
}
}
语法格式:
- 无参无返回值:
()->{method body}; - 无参有返回值:
()->{method body; return }; - 有参无返回值:
(ParameterType Parameter)->{method body}; - 有参有返回值:
(ParameterType Parameter)->{method body;return Parameter};
Lambda表达式的引用方法:
Lambda表达式支持只想一个外部的方法;
语法格式:
方法归属者::方法名 静态方法的归属者为类名,普通方法归属者为对象
/**
* 函数式接口
* 有一个参数的有返回值方法
*/
@FunctionalInterface
interface ReturnOneParam{
int add(int a);
}
package com.lzl.service.impl;
public class Test2 {
public static void main(String[] args) {
ReturnOneParam returnOneParam = a -> doubleNum(a);
//相当于调用的doubleNum
System.out.println(returnOneParam.add(10) );
}
/**
* 函数式接口的实现类;
* 要求:
* 参数个数和参数类型与接口的抽象方法保持一致;
* 返回值类型要与函数接口中的抽象方法的返回值类型保持一致
* @param a
* @return
*/
public static int doubleNum(int a){
return 2*a;
}
}
当调用外部类里的实现方法,将doubleNum(int a)方法移到Test类内:
package com.lzl.service.impl;
public class Test2 {
public static void main(String[] args) {
//因为是静态方法,类名::方法名
ReturnOneParam returnOneParam = Test::doubleNum;
//相当于调用的doubleNum
System.out.println(returnOneParam.add(10) );
}
}
普通方法:
/**
* 普通方法
* @param a
* @return
*/
public int addNum(int a){
return 20+a;
}
Test test = new Test();
ReturnOneParam returnOneParam1 = test::addNum;
System.out.println(returnOneParam1.add(10));
Lambda表达式创建线程:
创建线程的常见方式有继承Thread类,实现Runnable接口;其实Runnable接口的实现方法就是一个Lambda表达式,所以可以在创建线程时直接使用Lambda表达式来进行实现线程的run();
package com.lzl.service.impl;
/**
* 使用Lambda表达式来创建线程
*/
public class Test3 {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()+" 开始");
new Thread(()->{
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"lambda Thread").start();
System.out.println(Thread.currentThread().getName()+" 结束");
}
}
Lambda表达式操作集合:
遍历集合可以使用for循环和foreach循环,foreach循环就是通过lambda表达式的方式来遍历集合的元素;
集合的foreach()方法都会去调用这个方法,发现参数其实是一个函数式接口,所以可以使用Lambda表达式进行实现这个accept()方法;
/**
* 实现Consumer接口
*/
class ConsumerImpl implements Consumer{
@Override
public void accept(Object o) {
System.out.print(o);
}
}
package com.lzl.service.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
* 使用lambda表达式遍历集合
*/
public class Test4 {
public static void main(String[] args) {
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
//使用foreach循环,内部使用lambda表达式
Consumer consumer = new ConsumerImpl();
list.forEach(consumer);
System.out.println();
System.out.println("**************************************");
}
}
accept()这个抽象方法是一个无返回值但是有一个参数的抽象方法,如果格式符合,可以直接引用来作为这个方法的实现方法(lambda表达式的方法引用)。
因为System.out.println()这个方法的格式与accept()方法一致,所以可以这么写:
public class Test4 {
public static void main(String[] args) {
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
//使用foreach循环,内部使用lambda表达式
// Consumer consumer = new ConsumerImpl();
// list.forEach(consumer);
// System.out.println();
System.out.println("**************************************");
list.forEach(System.out::println);
}
}
也可以这么写:
list.forEach(x->{
if ((Integer)x>3){
System.out.println(x);
}
});
删除集合元素:
集合删除元素,有一个方法:removeIf();
需要传一个Predicate类型的参数;这个Predicate接口也是一个函数式接口,所以也可以使用lambda表达式进行实现Predicate(T);
package com.lzl.service.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
* 使用lambda表达式操作集合
*/
public class Test4 {
public static void main(String[] args) {
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
//删除集合元素
list.removeIf(x -> (Integer)x==1);
list.forEach(System.out::println);
}
}
对集合元素进行排序:
可以使用sort()方法:
package com.lzl.service.impl;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class Test5 {
public static void main(String[] args) {
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(4);
list.add(3);
list.add(5);
Comparator c = new CompareImpl();
list.sort(c);
list.forEach(System.out::println);
}
}
class CompareImpl implements Comparator<Integer>{
//重写比较方法
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
}
package com.lzl.service.impl;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class Test5 {
public static void main(String[] args) {
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(4);
list.add(3);
list.add(5);
//使用comparator类的自然排序方法
list.sort(Comparator.naturalOrder());
list.forEach(System.out::println);
}
}
Lambda表达式的闭包:
package com.lzl.service.impl;
/**
* Lambda表达式的闭包
*/
public class Test6 {
public static void main(String[] args) {
final int a = 10;
ReturnOneParam returnOneParam = new ReturnOneParam() {
@Override
public int add(int a) {
return a;
}
};
System.out.println(returnOneParam.add(10));
}
}
外部变量必须是final,也就是说使用lambda表达式实现匿名内部类时,变量必须是final类型。