Java——Lambda表达式、方法引用及内建函数式接口

1.Lambda表达式

面向对象的基础上支持函数式编程

  • 1.1 约束:

接口有且仅有一个抽象方法,如果存在两个抽象方法,则无法使用函数式编程。

  • 接口有且仅有一个抽象方法,且想要转化为lambda表达式,加注解 @FunctionalInterface——表明其是一个函数接口。此注解会检查该接口中是否只存在一个抽象方法,当出现多个抽象方法时,会编译报错。

  • 1.2 语法:

  • 1.1.1

如果实现抽象方法的方法体中只有一条命令,大括号可以省略

package com.qqycc;

/**
 * 方法体只有一条命令的Lambda
 * Author: qqy
 */

@FunctionalInterface
interface Message{
    void chat();
}

public class Test {
    public static void main(String[] args) {
        // 接口不能实例化
        // 匿名内部类创建实例化对象
        Message msg=new Message() {
            @Override
            public void chat() {
                System.out.println("匿名内部类实现的message聊天");
            }
        };

        //Lambda表达式
        Message msg1=()-> System.out.println("Lambda实现的message聊天");

        msg.chat();
        msg1.chat();
    }
}
  • 1.1.2

如果抽象方法参数只有一个,参数列表的括号可以省略

   注意:同一作用域下,参数列表中的参数名不能和其他变量名冲突

package com.qqycc.lambda1;

/**
 * 抽象方法只有一个参数
 * Author: qqy
 */

@FunctionalInterface
interface IMessage{
    void print(String msg);
}

public class Test2 {
    public static void main(String[] args) {
        IMessage msg=new IMessage(){
            @Override
            public void print(String msg) {
                System.out.println(msg);
            }
        };

        //参数列表中的参数名不能和其他变量名冲突
        IMessage msg1=m-> System.out.println(m+" bonsoir");

        msg.print("hello"); //hello
        msg1.print("bonjour");  //bonjour bonsoir
    }
}
  • 1.1.3

如果抽象方法实现中只有return一条语句,则return和大括号可以省略,直接使用语句的结果就是返回值。

package com.qqycc.lambda1;

/**
 * 有return的Lambda
 * Author: qqy
 */

@FunctionalInterface
interface IAdd {
    int add(int x,int y);
}

public class Test {
    public static void main(String[] args) {
        IAdd add=new IAdd() {
            @Override
            public int add(int x, int y) {
                return x+y;
            }
        };

        //函数式编程
        IAdd add1=(x, y)-> x+y+10;

        System.out.println(add.add(10,20));  //30
        System.out.println(add1.add(10,20)); //40
    }
}
  • 1.1.4

标准写法(不简写):

接口名 变量名=(参数列表)->{
      具体的方法体实现
           [return 语句;]
};
package com.qqycc.lambda1;

/**
 * 标准写法的Lambda
 * Author: qqy
 */

@FunctionalInterface
interface IAdd{
    int add(int x,int y);
}

public class Test1 {
    public static void main(String[] args) {
        IAdd add=new IAdd(){
            @Override
            public int add(int x, int y) {
                int result=x+y;
                result+=5;
                return result;
            }
        };

        IAdd add1= (x, y) -> {
            int result=x+y;
            result+=10;
            return result;
        };

        System.out.println(add.add(10,20));   //35
        System.out.println(add1.add(10,20));  //40
    }
}

2.方法引用-与Lambda表达式搭配使用

给现有方法起一个别名

  • 2.1 引用静态方法

类名称 :: 静态方法名称;
package com.qqycc;

/**
 * 引用静态方法
 * Author: qqy
 */

interface IUtil<P,R>{   //泛型
    R switchPara(P p);   //P类型—>R类型
}

public class Test {
    public static void main(String[] args) {
        //接口对象覆写抽象方法,该抽象方法的实现照用String的valueOf方法
        IUtil<Integer,String> util=String :: valueOf;
        //相当于调用String.valueOf(10);
        System.out.println(util.switchPara(10));
        System.out.println(Integer.valueOf(10));
    }
}
  • 2.2 引用对象方法

实例化对象 :: 普通方法;
package com.qqycc;

/**
 * 引用对象方法
 * Author: qqy
 */
interface IUtil1<R>{   //泛型
    R switchPara();   //P类型—>R类型
}

public class Test1 {
    public static void main(String[] args) {
        IUtil1<String> util="hello"::toUpperCase;
        //相当于调用"hello".toUpperCase();
        System.out.println(util.switchPara());
        System.out.println("hello".toUpperCase());
    }
}
  • 2.3 引用类中普通方法

类名称 :: 普通方法;
package com.qqycc;

/**
 * 引用类中普通方法
 * Author: qqy
 */
interface IUtil2<R,P>{
    R compare(P p1,P p2);
}

public class Test2 {
    public static void main(String[] args) {
        IUtil2<Integer,String>util=String::compareTo;
        //相当于调用String.compareTo();
        System.out.println(util.compare("1","2"));
        System.out.println("1".compareTo("2"));
    }
}
  • 2.4 引用构造方法

类名称 :: new
package com.qqycc;

/**
 * 引用构造方法
 * Author: qqy
 */

class Person{
    private String name;
    private Integer age;
    public Person(String name,Integer age){
        this.name=name;
        this.age=age;
    }

    @Override
    public String toString(){
       return "Person{"+"name="+this.name+"age="+this.age+"}";
    }
}

interface IUti3<R,PN,PR>{
    R createPer(PN p1,PR p2);
}

public class Test3 {
    public static void main(String[] args) {
        IUti3<Person,String,Integer>util=Person::new;
        //相当于调用了Person的new Person();
        System.out.println(util.createPer("张三",45));
        Person per=new Person("张三",45);
        System.out.println(per);
    }
}

3.内建函数式接口

Lamdba的核心——函数式接口。

函数式接口的核心——只有一个抽象方法。

  • 函数式编程分为以下四种接口:
  • 3.1 功能型函数式接口

根据一个入参,返回一个结果。

public interface Function<T, R> R apply(T t); 
package com.qqycc.bulidin;

import java.util.function.Function;
import java.util.function.IntFunction;

/**
 * 功能型函数接口
 * Author: qqy
 */
public class Test {
    public static void main(String[] args) {
        Function<Object, String> function = (value) -> {
            return value.toString();
        };
        String str = function.apply("Bonjour");
        System.out.println(str);

        //参数确定,返回值不确定
        IntFunction intFunction=String::valueOf;
        System.out.println(intFunction.apply(100));
    }
}
  • 3.2 供给型函数式接口

通过函数调用,返回一个对象

 public interface Supplier T get();
package com.qqycc.bulidin;

import java.util.function.Supplier;

/**
 * 供给型函数接口
 * Author: qqy
 */
class Person{
    public String name;
    public int age;

    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }

    public String toString(){
        return "Person{name="+this.name+"age="+this.age+"}";
    }
}

public class Test1 {
    public static void main(String[] args) {
        Supplier<Person> supplier=()->{
            return new Person("Mary", 18);
        };
        System.out.println(supplier.get());

        Supplier<String>supplier1="Hello"::toUpperCase;
        System.out.println(supplier1.get());
    }
}

  • 功能型+供给型结合使用

package com.qqycc.bulidin;

import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 功能型+供给型
 * Author: qqy
 */

class Person1{
    public String name;
    public int age;

    public Person1(String name,int age){
        this.name=name;
        this.age=age;
    }

    public String toString(){
        return "Person{name="+this.name+"age="+this.age+"}";
    }
}

public class Test2 {
    public static void main(String[] args) {
        //y=f(x)   x->Supplier,y->String
        Function<Supplier<Person>, String> function=(s)->{
            return s.get().toString();
        };
        //x=g()    (),x->Person
        Supplier<Person> s=()->{
            return new Person("Mary",18);
        };

        String res=function.apply(s);
        System.out.println(res);
    }
}

  • 3.3 消费型函数式接口

有参数,没有返回值

public interface Consumer void accept(T t);
package com.qqycc.bulidin;

import java.util.function.Consumer;

/**
 * 消费型函数式接口
 * Author: qqy
 */
public class Test3 {
    public static void main(String[] args) {
        Consumer<String> consumer=(str)->{
            System.out.println(str);
        };
        consumer.accept("Hello");
        
        Consumer<String[]> consumer1=(strs)->{
            for(String item:strs){
                System.out.println(item);
            }
        };
        consumer1.accept(new String[]{"v","i","e"});

        Consumer<String> consumer2=System.out::println;  //引用对象方法 out是一个对象
        consumer2.accept("C'est la vie");
    }
}
  • 3.4 断言型接口

传入参数,返回值为boolean类型

public interface Predicate boolean test(T t); 
package com.qqycc.bulidin;

import java.util.function.Predicate;

/**
 * Author: qqy
 */
class Person2{
    public String name;
    public int age;

    public Person2(String name,int age){
        this.name=name;
        this.age=age;
    }

    public String toString(){
        return "Person{name="+this.name+"age="+this.age+"}";
    }
}

public class Test4 {
    public static void main(String[] args) {
        Predicate<String> predicate="Hello"::endsWith;
        //等价于"Hello".endsWith
        boolean res=predicate.test("o");
        System.out.println(res);  //true

        //参数 Object类型,判断——若参数对象是由Person类实例化的,返回true,否则返回false
        Predicate<Object> predicate1=(obj)->{
            return obj instanceof Person2;
        };
        System.out.println(predicate1.test("Hello")); //false
        System.out.println(predicate1.test(new Person2("Lila",20)));  //true

        predicate1="String"::equals;
        System.out.println(predicate1.equals("String"));  //false
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42142477/article/details/84765447