Lamda表达式
1.什么是Lamda?
Lamda 是JAV 8 添加的一个新的特性,说白了Lamda 就是一个匿名函数。
为什么要使用Lamda?
使用Lamda表达式可以对一个接口实现非常简洁的实现。
比如说我们要实现一个比较大小的接口:
方式一:接口的实现类来完成此功能。
public class Program {
public static void main(String[] args) {
MyComparator myComparator = new MyComparator();
myComparator.compar(4, 6);
}
}
interface Comparator {
int compar(int a, int b);
}
class MyComparator implements Comparator {
@Override
public int compar(int a,int b) {
return a-b;
}
}
方式二:匿名内部类
public class Program {
public static void main(String[] args) {
Comparator comparator = new Comparator() {
@Override
public int compar(int a, int b) {
return a-b;
}
};
int compar = comparator.compar(4, 6);
System.out.println(compar);
}
}
interface Comparator {
int compar(int a, int b);
}
方式三:Lamda 表达式
public class Program {
public static void main(String[] args) {
Comparator comparator = (a,b)->a-b;
int compar = comparator.compar(4, 6);
System.out.println(compar);
}
}
interface Comparator {
int compar(int a, int b);
}
Lamda对接口的要求是什么?
虽然可以使用Lamda 表达式对某些接口进行简单的实现,但并不是所有的接口都可以用Lamda表达式来实现。要求接口中定义的必须是要实现的抽象方法只能是一个
*JAVA 8 对接口家里一个新的特性:default
*
@FunctionalInterface修饰函数式接口的,接口中的抽象方法只有一个。
如果有多个抽象方法就会报错
2.Lamda基本语法
首先需要注意的是 Lamda 是一个匿名函数那么有以下几个关注点
-
参数列表名
-
方法体
-
返回值类型 (在Lamda 中返回值不用显示的写出)
-
方法名(匿名不用关注)
符号 | 含义 |
---|---|
() | 用来描述参数列表 |
{} | 用来表示方法体 |
-> | Lamda运算符 读作 goes to |
1.无参无返回值
@FunctionalInterface
public interface LamdaNoneReturnNoneParamter {
void test();
}
class imTest{
public static void main(String[] args) {
LamdaNoneReturnNoneParamter lamdaNoneReturnNoneParamter = ()->{
System.out.print("无参无返回值");
} ;
}
}
2.无返回值单个参
@FunctionalInterface
public interface LamdaNoneReturnNoneParamter {
void test(int i);
}
class imTest{
public static void main(String[] args) {
LamdaNoneReturnNoneParamter lamda1 = (int c)->{
System.out.print(c);
System.out.print("无返回值单个参");
} ;
lamda1.test(10);
}
}
3.无返回值多个参
@FunctionalInterface
public interface LamdaNoneReturnMutipleParamter {
void test(int a, int b);
}
class imTest3{
public static void main(String[] args) {
LamdaNoneReturnMutipleParamter lamda3 = (int c,int d)->{
System.out.println(c+"--------"+d);
System.out.println("无返回值多个参");
};
lamda3.test(11, 33);
}
}
4.有返回值没有参
@FunctionalInterface
public interface LamdaSingleReturnNoneParam {
int test();
}
class imTest4{
public static void main(String[] args) {
LamdaSingleReturnNoneParam lamda4 = ()->{
System.out.println("有返回值没有参");
return 10;
};
int demo = lamda4.test();
System.out.println(demo);
}
}
5.有返回值单个参数
@FunctionalInterface
public interface LamdaSingleReturnSingleParamter {
int test(int d);
}
class imTest5{
public static void main(String[] args) {
LamdaSingleReturnSingleParamter lamda5 = (int a)->{
System.out.println("有返回值单个参数");
return a*10;
};
int demo = lamda5.test(10);
System.out.println(demo);
}
}
6.有返回值多个参数
@FunctionalInterface
public interface LamdaSingleReturnMultipleParamter {
int test(int a, int b, int c);
}
class imTest6{
public static void main(String[] args) {
LamdaSingleReturnMultipleParamter lamda6 = (int a,int b,int c)->{
System.out.println("有返回值单个参数");
return a*b*c;
};
int demo = lamda6.test(10,2,3);
System.out.println(demo);
}
}
3.Lamda语法精简
-
由于在接口的抽象方法中,已经定义了参数的数量和类型,所以 可以将参数的类型可以省略(如果需要省略参数类型,则每个参数的类型都要省略)。
-
如果参数列表中,参数的数量只有一个,此时小括号可以省略。
-
方法大括号:如果方法体中只有一条语句时,大括号可以省略。
-
如果方法体中唯一的一条语句是一个返回语句,return也可以省略。
4.语法进阶
方法引用:可以快速的将一个Lamda表达式的实现指向一个已经实现的方法。
语法:方法的隶属者::方法名,需要注意参数类型和类型一定要和接口一致。
@FunctionalInterface
public interface LamdaSingleReturnSingleParamter {
int test(int d);
}
import faces.LamdaSingleReturnSingleParamter;
class Syntax2 {
public static void main(String[] args) {
LamdaSingleReturnSingleParamter lamda = a -> change(a);
//简化为:
LamdaSingleReturnSingleParamter lamda2 = Syntax2::change;
}
private static int change(int a) {
return a * 2;
}
}
构造方法的引用:
无参
class syntax3 {
public static void main(String[] args) {
PersonCreate person = ()-> new Person("zs","ls");
System.out.println(person);
//构造函数的引用
PersonCreate person2 = Person::new;
Person zs = person2.getPerson();
System.out.println(zs);
}
}
interface PersonCreate {
Person getPerson();
}
有参
class syntax3 {
public static void main(String[] args) {
//构造函数的引用
PersonCreate person2 = Person::new;
Person zs = person2.getPerson("zs","ls");
System.out.println(zs);
}
}
interface PersonCreate {
Person getPerson(String name,String sex);
}
综合练习:
package syntax;
import java.util.ArrayList;
class syntax3 {
public static void main(String[] args) {
ArrayList<Person> personList = new ArrayList<>();
personList.add(new Person("zs",12 ));
personList.add(new Person("we",142 ));
personList.add(new Person("ee",52 ));
personList.add(new Person("ww",3 ));
personList.add(new Person("ee",122 ));
personList.add(new Person("qew",2 ));
personList.add(new Person("ss",7 ));
personList.sort((o1,o2)->o2.age-o1.age);
System.out.println(personList);
}
}
换成TreeSet
package syntax;
import java.util.TreeSet;
class syntax3 {
public static void main(String[] args) {
TreeSet<Person> set = new TreeSet<>();
set.add(new Person("zs",12 ));
set.add(new Person("we",142 ));
set.add(new Person("ee",52 ));
set.add(new Person("ww",3 ));
set.add(new Person("ee",122 ));
set.add(new Person("qew",2 ));
set.add(new Person("ss",7 ));
System.out.println(set);
}
}
person对象不能转型为Comparable ,因为set集合是自带排序,但是如果是person对象的话,就无法判断其大小,
根据源码可知,需要有一个Comparator 对象的实现类来提供对象的比较规则。因此代码如下:
package syntax;
import java.util.TreeSet;
class syntax3 {
public static void main(String[] args) {
TreeSet<Person> set = new TreeSet<>((o1,o2)->o1.age-o2.age);
set.add(new Person("zs",12 ));
set.add(new Person("we",142 ));
set.add(new Person("ee",52 ));
set.add(new Person("ww",3 ));
set.add(new Person("ee",122 ));
set.add(new Person("qew",2 ));
set.add(new Person("ss",7 ));
System.out.println(set);
}
}
集合遍历实现:
package syntax;
import java.util.ArrayList;
import java.util.Collections;
class syntax3 {
public static void main(String[] args) {
ArrayList<Integer> arry = new ArrayList<>();
Collections.addAll(arry, 1,3,2,4,5,6,8,7,9,10);
arry.forEach(element ->{
if(element % 2 ==0) {
System.out.println(element);
}
});
}
}
实现判断删除
package syntax;
import java.util.ArrayList;
import java.util.ListIterator;
class syntax3 {
public static void main(String[] args) {
ArrayList<Person> personList = new ArrayList<>();
personList.add(new Person("zs",12 ));
personList.add(new Person("we",142 ));
personList.add(new Person("ee",52 ));
personList.add(new Person("ww",3 ));
personList.add(new Person("ee",122 ));
personList.add(new Person("qew",2 ));
personList.add(new Person("ss",7 ));
ListIterator<Person> iterator = personList.listIterator();
while (iterator.hasNext()) {
Person person = (Person) iterator.next();
if(person.age > 10) {
iterator.remove();
}
}
System.out.println(personList);
}
}
使用Lamda 表达式实现
package syntax;
import java.util.ArrayList;
class syntax3 {
public static void main(String[] args) {
ArrayList<Person> personList = new ArrayList<>();
personList.add(new Person("zs",12 ));
personList.add(new Person("we",142 ));
personList.add(new Person("ee",52 ));
personList.add(new Person("ww",3 ));
personList.add(new Person("ee",122 ));
personList.add(new Person("qew",2 ));
personList.add(new Person("ss",7 ));
//将集合中的每个元素都带入到test方法中进行比较,如果返回true 则删除这个元素。
personList.removeIf(element -> {
if(element.age % 2== 0) {
return true;
}
return false;
});
System.out.println(personList);
}
}
使用lamda 实例化线程对象
5.Lamda系统内置
package syntax;
public class syntax3 {
public static void main(String[] args) {
//需求:实现runable 接口开启一个线程,做一个数字输出
Thread thread = new Thread(()->{
int i = 0;
do {
System.out.println(i++);
} while (i<=10);
});
thread.start();
}
}
6.系统内置的函数式接口
在java.util.function下面的所有接口都是系统内置的函数式接口
-
Predicate<T> 参数 : T 返回值 :boolean
实体 | 参数 | 返回值 |
---|---|---|
IntPredicate | int | boolean |
LongPredicate | long | boolean |
DoublePredicate | double | boolean |
-
Consumer<T>参数 : T 返回值 :void
实体 | 参数 | 返回值 |
---|---|---|
IntConsumer | Int | void |
LongConsumer | Long | void |
DoubleConsumer | Double | void |
-
Supplier<T> 参数 : 无 返回值 :T
-
UnaryOperator<T> 参数 : T返回值 :T
省略。。。。。。
7.闭包
package syntax;
import java.util.function.Supplier;
public class syntax3 {
public static void main(String[] args) {
Integer num = getNum().get();
System.out.println(num);
}
private static Supplier<Integer> getNum() {
int num = 10;
return ()->{
return num;
};
}
}
//10