Java之lamda表达式(函数式接口应用)


lamda表达式:

使用Lamda表达式需要一个重要的实现要求: SAM(Single Abstract Method)

在之前的匿名内部类中存在一个问题:

IMessage msg = new IMessage(){  // 匿名内部类
            public void send(String str){
                System.out.println(str);
            }
        };

以上代码仅需要一个功能就是:

System.out.println(str);

但是却使用了完整的面向对象结构来表达;

那么为了简化这种结构,就引出了Lamda表达式:

public class Main {
    public static void main(String[] args) {
        IMessage msg = (str) ->{
            System.out.println(str);
        };
        msg.send("I am here!Lamda!");
    }
}

在下面的接口中只有一个send()方法,除此之外没有其它任何方法,所以这种接口就被称为函数式接口

而只有函数式的接口才能被Lamda表达式接受。

 


@FunctionalInterface    // 函数式接口
public interface IMessage {
    public void send(String str);
    public static IMessage getInstance(){
        return new IMessage() { //静态的匿名内部类
            @Override
            public void send(String str) {
                System.out.println(str);
            }
        };
    }
}

函数式接口中的abstract方法永远只能有一个,其后可以增加default、static的普通方法。


@FunctionalInterface    // 函数式接口
public interface IMessage {
    public void send(String str);
    public default void sub(){
        System.out.println("jianfa");
    }
    public static void sum(){
        System.out.println("jiafa ");
    }
    public static IMessage getInstance(){
        return new IMessage() { //静态的匿名内部类
            @Override
            public void send(String str) {
                System.out.println(str);
            }
        };
    }
}

Lamda表达式格式:

  - 方法没有参数:() -> {};

  - 方法有参数: (参数,参数) -> {};

  - 如果现在只有一行语句返回:(参数,参数) -> 返回语句;

方法的引用:

相当于将某个类的方法使用另一个名称表示,并传入对应的参数,方法的功能都是一样。

存在四种格式:

  - 引用静态方法:类名称 :: static方法

  - 引用某个实例对象方法:实例化对象 :: 普通方法

  - 引用特定类型的方法:特定类 :: 普通方法

  - 引用构造方法:类名称 :: new

以泛型定义方法的格式应用函数式接口:
@FunctionalInterface
public interface IFunction {   // R是返回值类型,P是参数
    public R 转换 (P p) ; // R定义返回值类型,P定义参数
}
@FunctionalInterface
public interface IFunctions {    // R是返回值类型
    public R upper () ;
}
package Demo_1_28_以泛型定义方法的格式应用函数式接口;

public interface IFunctionss 

{//P是参数类型 public int compare(P p1,P p2); }

package Demo_1_28_以泛型定义方法的格式应用函数式接口;

public interface IFunctionsss {
    public R create(String s, int a);
}
package Demo_1_28_以泛型定义方法的格式应用函数式接口;

public class Main {
    public static void main(String[] args) {
        // :: 之前是返回值类型,:: 之后是某种方法,valueOf是static方法
        IFunction fun = String :: valueOf;  // 两个参数,返回值是字符串,参数是Integer
        String str = fun.转换(100);   //此时转换方法和valueOf是同一个方法
        System.out.println(str.length());
        // toUpperCase需要实例化对象才能使用,"www.baidu.com"就是一个字符串对象。
        IFunctions fun1 = "www.baidu.com" :: toUpperCase;   // 返回支付串,
        System.out.println(fun1.upper());   //此时upper方法和toUpperCase是同一个方法
        // 引用指定类的方法
        IFunctionss fun2 = String :: compareTo;
        System.out.println(fun2.compare("A","a"));  //此时compare方法和compareTo是同一个方法
        // 引用构造方法
        IFunctionsss fun3 = Person :: new;
        System.out.println(fun3.create("张三",19));   //此时create方法和Person的构造方法是同一个方法
    }
}

方法引用并不是替代品,只是弥补了此项功能的不足,多出一种选择。

内建的函数式接口:

在系统之中专门提供有一个java.util.function的开发包,可以直接进行函数式接口的使用:

  - 功能性函数式接口:接口都是以Function为后缀

接口定义 接口使用
@FunctionalInterface
public interface Function<T,R> {
public R apply (T t) ;

}

import java.util.function.Function;

public class Main {
    public static void main(String[] args) {
        Function fun = "** Hello" :: startsWith;
        System.out.println(fun.apply("**"));    // true,此时的apply方法就是startsWith方法
    }
}

  - 消费型函数式接口:只能够进行数据的处理操作,而没有任何的返回:

   · 在进行系统数据输出的时候使用System.out.println();

接口定义 接口使用

@FunctionalInterface
public interface Consumer<T> {   public void accept (T t); }
 
import java.util.function.Consumer;

public class Main {
    public static void main(String[] args) {
        Consumer fun1 = System.out :: println;  // System.out类下的println方法
        fun1.accept("消费性接口应用,输出语句!");  // 此时的accept方法就是println方法
} }

  - 供给型函数式接口:

    · 在String类中提供了转先写的方法,这个方法没有接收参数,但是有返回值。

      |- 方法: public String toLowerCase();

接口定义 接口使用
@FunctionalInterface
public interface Supplier{
  public T get() ;
}
 
import java.util.function.Supplier;

public class Main {
    public static void main(String[] args) {
        Supplier fun4 = "WWW.BAIDU.COM" :: toLowerCase;   // 供给型,不接收任何参数,只有返回值
        System.out.println(fun4.get());     // 此时get方法就是toLowerCase方法;
    }
}

  - 断言型函数式接口:进行判断处理

    ·  在String类中有一个方法是equalsIgnoreCase()方法;

接口定义 接口使用
@FunctionalInterface
public interface Predicate{
  public boolean test (T t)
}
 
import java.util.function.Predicate;

public class Main {
    public static void main(String[] args) {
        // 断言型函数式接口
        Predicate fun5 = "www" :: equalsIgnoreCase;
        System.out.println(fun5.test("wwW"));
    }
}

如果JDk提供的函数式接口已经满足我们的需求,那么就没有必要重写定义了。