简介
什么是lambda?Java8新特性,说白了就是匿名函数
使用lambda来干嘛?可以对接口里的函数进行最简单的实现;想要对接口里的函数进行实现,一般来讲可以有三种方式
- 类实现接口
- 匿名内部类
- lambda
很显然:第三种方式最简单
public class LambdaTest {
public static void main(String[] args) {
// 1.实现类
MyCompartor compartor = new MyCompartor();
compartor.compare(2,5);
}
}
interface Compartor{
int compare(int a,int b);
}
class MyCompartor implements Compartor{
@Override
public int compare(int a, int b) {
return a-b;
}
}
public class LambdaTest {
public static void main(String[] args) {
// 2.匿名内部类
Compartor compartor=new Compartor() {
@Override
public int compare(int a, int b) {
return a-b;
}
};
compartor.compare(3,6);
}
}
interface Compartor{
int compare(int a,int b);
}
public class LambdaTest {
public static void main(String[] args) {
// 3.lambda方式
Compartor compartor=(int a,int b)->a-b;
}
}
interface Compartor{
int compare(int a,int b);
}
lambda虽然方便但是要求接口中只有一个抽象方法;
Java8之后可以用default关键字来修饰接口中的方法,具体参照其他博主的文档:【java接口中的default方法】,这个可以解决如果接口中有多个方法,但是又想用lambda的情况。
可以用@FunctionalInterface注解来标注接口,具体是函数式接口,只有一个抽象方法的接口。@FunctionalInterface标注的接口用lambda肯定没问题。
基础语法
语法进阶
方法引用:
public class LambdaTest {
public static void main(String[] args) {
//一我们可以这样写
MyOperation add=(m,n)->m+n;
//二可以把这个+的操作提取出来
MyOperation add1=(m,n)->addOperate(m,n);
System.out.println(add1.operate(2,5));
//三进一步写成方法引用
MyOperation add2=LambdaTest::addOperate;
}
public static int addOperate(int a, int b){
return a+b;
}
}
interface MyOperation{
int operate(int a,int b);
}
这三种实现的功能都一致。
方法引用:可以将lambda的实现指向已有的方法,语法为方法的隶属者::方法名;特别要注意方法中的参数类型,数量,返回值等都要和接口中的方法保持一致。(隶属者一般是对象或者类,如果是静态方法,隶属者就是类,如果是非静态方法,隶属者就是对象)
构造方法的引用
构造方法的引用和普通方法的引用,本质上没有区别,只是写法形式略有不同
public class Person {
private String name;
private Integer age;
public Person() {
System.out.println("无参");
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
System.out.println("有参");
}
}
package lambda;
public class LambdaTest {
public static void main(String[] args) {
//1.调用无参的构造函数
PersonService1 p1=Person::new;
//2.调用有参的构造函数
PersonService2 p2=Person::new;
System.out.println(p1.getPerson());
System.out.println(p2.getPerson("王小二",87));
}
}
interface PersonService1{
Person getPerson();
}
interface PersonService2{
Person getPerson(String name,Integer age);
}
lambda的使用案例
1.集合排序
package lambda;
public class Person {
private String name;
private Integer age;
public Person() {
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class LambdaTest {
public static void main(String[] args) {
ArrayList<Person> list=new ArrayList<>();
list.add(new Person("梅西",32));
list.add(new Person("大罗",43));
list.add(new Person("苏亚雷斯",33));
list.add(new Person("C罗",35));
list.add(new Person("迪巴拉",26));
//这里需要传入一个实现Comparator接口(函数式接口)的对象,我们可以用lambda来实现
list.sort((Person p1,Person p2)-> p1.getAge()-p2.getAge());
System.out.println(list);
}
}
2.TreeSet排序
public class LambdaTest {
public static void main(String[] args) {
TreeSet<Person> set =new TreeSet<>((Person p1,Person p2)->{
if (p1.getAge()>=p2.getAge()){
return 1;
}
return -1;
});
set.add(new Person("梅西",32));
set.add(new Person("大罗",43));
set.add(new Person("苏亚雷斯",33));
set.add(new Person("C罗",35));
set.add(new Person("迪巴拉",26));
set.add(new Person("xxx",33));
System.out.println(set);
}
}
注意:其实TreeSet排序还有另外一种实现方式,但是Person要实现Comparable接口。不然就要在创建Set的时候传入Comparator对象。
如果Comparator的compare的方法返回0,会认为这两个对象是一样的,导致set集合里只有其中之一。
3.集合遍历
public class LambdaTest {
public static void main(String[] args) {
ArrayList<Person> list=new ArrayList<>();
list.add(new Person("梅西",32));
list.add(new Person("大罗",43));
list.add(new Person("苏亚雷斯",33));
list.add(new Person("C罗",35));
list.add(new Person("迪巴拉",26));
list.add(new Person("xxx",33));
//可以接收Consumer接口的对象
list.forEach(System.out::println);
System.out.println("-----------------------------");
//遍历输出偶数年龄的球员
list.forEach(p1->{
if (p1.getAge()%2==0){
System.out.println(p1);
}
});
}
}
4.根据条件删除集合中的元素(删除年龄大于40的球星)
public class LambdaTest {
public static void main(String[] args) {
ArrayList<Person> list=new ArrayList<>();
list.add(new Person("梅西",32));
list.add(new Person("大罗",43));
list.add(new Person("苏亚雷斯",33));
list.add(new Person("C罗",35));
list.add(new Person("迪巴拉",26));
list.add(new Person("xxx",33));
//用传统的方法删除
/**
* Iterator<Person> iterator = list.iterator();
* while (iterator.hasNext()){
* Person p=iterator.next();
* if (p.getAge()>40){
* iterator.remove();
* }
* }
* */
//用lambda的方式来删除,需要传入Predicate接口的实例对象,接口有一个test方法,返回true代表删除这个元素
list.removeIf(p1->p1.getAge()>40);
System.out.println(list);
}
}
5.创建线程
public class LambdaTest {
public static void main(String[] args) {
Thread t=new Thread(()->{
//这里就是runf
for (int i=0;i<100;i++)
System.out.println(i);
});
t.start();
}
}
系统内置的函数式接口
主要在java.util.function.*里
可以多看看集合里的lambda的用法,比如ArrayList的foreach方法等
注意:
函数式接口不仅仅可以作为参数传入方法中,还可以作为返回值返回
public class Main {
public static void main(String[] args) {
System.out.println( method().get());
}
public static Supplier method(){
return ()->{
return "Hello World";
};
}
}