一、Lambda表达式介绍
1、Lambda表达式是java8中最重要的新功能之一。使用Lambda表达式可以替代只有一个抽象函数接口的实现,告别匿名内部类,代码看起来更简洁易懂。Lambda表达式同时还提示了对集合框架的迭代、遍历、过滤数据的操作
2、特点
(1)函数式编程
(2)参数类型自动推断
(3)代码量少,简洁3、应用场景
(1)任何有函数式接口的地方
二、Lambda表达式的使用
示例
Student
package com.msbline.lambda;
public class Student {
private String name;
private int age;
private int score;
public Student() {
}
public Student(String name, int age, int score) {
this.name = name;
this.age = age;
this.score = score;
}
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 int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + ''' +
", age=" + age +
", score=" + score +
'}';
}
}
接口:StudentFilter
package com.msbline.lambda.v1;
import com.msbline.lambda.Student;
public interface StudentFilter {
boolean compare(Student student);
}
实现类1:
public class AgeFilter implements StudentFilter {
@Override
public boolean compare(Student student) {
return student.getAge()>3;
}
}
实现类2:
package com.msbline.lambda.v1;
import com.msbline.lambda.Student;
public class ScoreFilter implements StudentFilter{
@Override
public boolean compare(Student student) {
return student.getScore()>1;
}
}
测试:
原始操作
package com.msbline.lambda.v1;
import com.msbline.lambda.Student;
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
ArrayList list = new ArrayList<>();
list.add(new Student("zhangsan",1,1));
list.add(new Student("lisi",8,2));
list.add(new Student("wangwu",3,3));
list.add(new Student("jack",9,4));
list.add(new Student("rose",5,5));
getByFilter(list,new AgeFilter());
System.out.println("-----------------");
getByFilter(list,new ScoreFilter());
}
public static void getByFilter(ArrayList students,StudentFilter filter){
ArrayList list = new ArrayList();
for (Student stu:students){
if(filter.compare(stu)){
list.add(stu);
}
}
print(list);
}
public static void print(ArrayList students){
for (Student stu:students){
System.out.println(stu);
}
}
}
lambda操作,都可以不用接口和实现类
package com.msbline.lambda.v1;
import com.msbline.lambda.Student;
import java.util.ArrayList;
public class Test3 {
public static void main(String[] args) {
ArrayList list = new ArrayList<>();
list.add(new Student("zhangsan",1,1));
list.add(new Student("lisi",8,2));
list.add(new Student("wangwu",3,3));
list.add(new Student("jack",9,4));
list.add(new Student("rose",5,5));
getByFilter(list,(e)->e.getAge()>3);
System.out.println("------------------");
getByFilter(list,(e)->e.getScore()>1);
System.out.println("------------------");
getByFilter(list,(e)->e.getName().length()>4);
}
public static void getByFilter(ArrayList students,StudentFilter filter){
ArrayList list = new ArrayList();
for (Student stu:students){
if(filter.compare(stu)){
list.add(stu);
}
}
print(list);
}
public static void print(ArrayList students){
for (Student stu:students){
System.out.println(stu);
}
}
}
三、函数式接口
只有一个抽象方法(Object类中的方法除外)的接口是函数式接口
四、Lambda表达式的原理
暂时搞不明白,后期补充
五、方法的引用
方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法,方法引用提供了一种引用而不执行方法的方式,如果抽象方法的实现恰好可以使用调用另外一个方法来实现,就有可能可以使用方法引用
1、静态方法引用
如果函数式接口的实现恰好可以通过调用一个静态方法来实现,那么就可以使用静态方法引用
package com.msbline.lambda.functionRef;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
public class Test2 {
public static void main(String[] args) {
// System.out.println(put());
Supplier s1 = ()->Test2.put();
System.out.println(s1.get());
Supplier s2 = Test2::put;
System.out.println(s2.get());
Supplier s3 = Fun::hehe;
System.out.println(s3.get());
Consumer c1 = Test2::getSize;
c1.accept(1);
Consumer c2 = (size)->Test2.getSize(size);
c2.accept(123);
Function f1 = (str)->str.toUpperCase();
Function f2 = (str)->Test2.toUpper(str);
Function f3 = Test2::toUpper;
Function f4 = Fun::toUpperCase;
System.out.println(f1.apply("abc"));
System.out.println(f2.apply("abc"));
System.out.println(f3.apply("abc"));
System.out.println(f4.apply("abc"));
}
public static void getSize(int size){
System.out.println(size);
}
public static String toUpper(String str){
return str.toUpperCase();
}
static String put(){
System.out.println("put......");
return "put";
}
}
class Fun{
public static String hehe(){
return "hehe";
}
public static String toUpperCase(String str){
return str.toUpperCase();
}
}
2、实例方法引用
如果函数式接口的实现恰好可以通过调用一个实例的实例方法来实现,那么久可以使用实例方法引用
package com.msbline.lambda.functionRef;
import com.msbline.threadPkg.Test;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
public class Test3 {
public String put(){
return "put......";
}
public void getSize(int size){
System.out.println("size:"+size);
}
public String toUppercase(String str){
return str.toUpperCase();
}
public static void main(String[] args) {
System.out.println(new Test3().put());
Supplier s1 = ()->new Test3().put();
Supplier s2 = ()->{return new Test3().put();};
Supplier s3 = new Test3()::put;
System.out.println(s1.get());
System.out.println(s2.get());
System.out.println(s3.get());
Test3 test3 = new Test3();
Consumer c1 = (size)->new Test3().getSize(size);
Consumer c2 = new Test3()::getSize;
Consumer c3 = test3::getSize;
c1.accept(123);
c2.accept(123);
c3.accept(123);
Function f1 = (str)->str.toUpperCase();
Function f2 = (str)->test3.toUppercase(str);
Function f3 = new Test3()::toUppercase;
Function f4 = test3::toUppercase;
System.out.println(f1.apply("abc"));
System.out.println(f2.apply("abc"));
System.out.println(f3.apply("abc"));
System.out.println(f4.apply("abc"));
}
}
3、对象方法引用
抽象方法的第一个参数类型刚好是实例方法的类型,抽象方法剩余的参数恰好可当作实例方法的参数,如果函数式接口的实现能由上面说的实例方法调用来实现的话,那么就可以使用对象方法引用
package com.msbline.lambda.functionRef;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
public class Test4 {
public static void main(String[] args) {
Consumer c1 = (Too too)->new Too().foo();
c1.accept(new Too());
Consumer c2 = (Too too) ->new Too2().foo();
c2.accept(new Too());
Consumer c3 = Too::foo;
c3.accept(new Too());
BiConsumer bc = (too2,str)->new Too2().show(str);
BiConsumer bc2 = Too2::show;
bc.accept(new Too2(),"abc");
bc2.accept(new Too2(),"def");
BiFunction bf1 = (e,s)->new Exec().test(s);
bf1.apply(new Too2(),"abc");
BiFunction bf2 = Exec::test;
bf2.apply(new Exec(),"def");
}
}
class Exec{
public int test(String name){
return 2;
}
}
class Too{
public Integer fun(String s){
return 1;
}
public void foo(){
System.out.println("foo");
}
}
class Too2{
public Integer fun(String s){
return 1;
}
public void foo(){
System.out.println("foo---too2");
}
public void show(String str){
System.out.println("show---too2"+str);
}
}
4、构造方法引用
如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用
package com.msbline.lambda.functionRef;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
public class Test5 {
public static void main(String[] args) {
Supplier s1 = ()->new Person();
s1.get();
Supplier s2 = Person::new;
s1.get();
Supplier s3 = ArrayList::new;
Supplier s4 = HashSet::new;
Supplier s5 = Thread::new;
Supplier s6 = String::new;
Consumer c1 = (age)->new Account(age);
Consumer c2 = Account::new;
Consumer c3 = Integer::new;
c1.accept(2);
c2.accept(2);
c3.accept(5);
Function f1 = (str)->new Account(str);
Function f2 = Account::new;
f1.apply("abc");
f2.apply("def");
}
}
class Account{
public Account() {
System.out.println("调用无参构造方法");
}
public Account(int age){
System.out.println("age参数构造"+age);
}
public Account(String str){
System.out.println("String 参数构造"+str);
}
}
class Person{
public Person() {
System.out.println("调用无参构造");
}
}