lambda表达式使用和示例

lambda表达式

什么是lambda

学习lamdba有两个结构十分关键,一个是lamdba自己,另一个是函数式接口

lamdba

  1. lamdba表达式本质上就是匿名方法,不能独立运行
  2. 用于实现函数式接口定义的另一个方法,因此lamdba会产生一个匿名类
  3. lamdba也常被称作闭包
  4. 引入了新的语法操作符 ->

函数式接口

  1. 只包含一个抽象方法的接口,这个方法说明了这个接口的意义和使用
  2. 函数式接口通常表示单个动作
  3. 有时被称作SAM类型,单抽象方法

lambda表达式示例

interface MyNumber{
    double getValue();
}
public static void main(String[] args){
    MyNumber myNum;
    myNum = ()-> 3.1415;
    System.out.println(myNum.getValue())
}

//输出
3.1415

块lambda

  1. 处理简单的赋值等操作可以使用单个表达式
  2. 处理复杂的语句可以使用块lambda,可以使用多条语句
  3. 最后必须显示的使用return 返回值

块lambda 阶乘示例

interface MyNum{
    int func(int n);
}
public void test1(){
        MyNum mm = (n)->{
            int result =1;
            for(int i=1;i<=n;i++){
                result *= i;
            }
            return result;
        };
        System.out.println(mm.func(4));
    }

泛型函数式接口

示例

interface SomeFunc<T>{
    T func(T t);
}
public void test2(){
        SomeFunc<Integer> num = (n)-> n*10;
        SomeFunc<String> str = (s)-> "hello " + s;

        System.out.println(num.func(10));
        System.out.println(str.func("tom"));

    }

当作参数传递

interface SomeFunc<T>{
    T func(T t);
}
 public String getResult(SomeFunc<String> some,String str){
        return some.func(str);
    }
  public void test3(){
        String str = "hello java for lambda";
        String ret = getResult((n)->{
            return n.toUpperCase();
        },str);
        System.out.println(ret);

        String ret1 = getResult((n)->{
            return new StringBuffer(str).reverse().toString();
        },str);

        System.out.println(ret1);
    }
//输出
HELLO JAVA FOR LAMBDA
adbmal rof avaj olleh

lambda 表达式与异常

  1. lambda可以抛出异常
  2. 异常必须和函数式接口throws抛出的异常一致

代码示例

interface DoubleNumberFun{
    double fun(double[] n)throws DoubleNumberException;
}
class DoubleNumberException extends Exception{
    public DoubleNumberException(){
        super("array empty");
    }
}
   public void test4() throws DoubleNumberException {

        DoubleNumberFun df = (n)->{
            if(n.length == 0)
                throw new DoubleNumberException();
            double sm = 0.0;
            for(int i=0;i<n.length;i++){
                sm += n[i];
            }
            return sm;
        };

       	System.out.println(df.fun(new double[]{1.0,2.0,3.0}));
        System.out.println(df.fun(new double[]{}));
    }
//输出

//6.0
//com.bai.lambda.DoubleNumberException: array empty

lambda 表达式变量捕获

  1. lambda 中可以显示或者隐式的使用this
  2. 使用局部变量默认是final 修饰,不能改变,不管有没有使用final。否则会提示Variable used in lambda expression should be final or effectively final

代码示例

interface MyNum{
    int func(int n);
}
int variable = 10;

public void test5(){
        int variable1 = 0;
        MyNum m = (n)->{
            int sum = 0;
            for(int i=0;i<n;i++){

                sum += i + variable1;
            }
            //此处报错
            //Variable used in lambda expression should be final or effectively final
            //variable1 = sum;
            return sum;
        };

        MyNum m1 = (n)->{
            int sum = 0;
            for(int i=0;i<n;i++){
                //Variable used in lambda expression should be final or effectively final
                sum += i + this.variable;
            }
            this.variable = sum;
            return sum;
        };

    }

方法引用

静态方法引用

  1. 形式: classname::methodName
  2. :: 是jdk8新添加分隔符,专门用于此处
  3. 函数式接口的方法要和静态方法兼容,比如下面的func 方法和strReverse兼容

代码示例

函数式接口

interface StringFunc{
    String func(String str);
}

静态方法

  public static String StrReverse(String str){
        char[] chars = new char[str.length()];
        for(int i=0;i<str.length();i++){
            chars[i] = str.charAt(str.length()-1-i);
        }
        return new String(chars);
    }

方法引用

public static String stringOpts(StringFunc func,String str){
        return func.func(str);
    }

测试方法

 public static void main(String[] args) {
        String result = stringOpts(MyStringOpts::StrReverse,"helllo lambda static");
        System.out.println(result);
    }
//输出
//citats adbmal ollleh

实例中使用

对象调用

objRef::methodname

需要先 new 对象在进行调用

interface StringFunc{
    String func(String str);
}
class ObjRef{

    public String reverse(String str){
        StringBuffer buf = new StringBuffer();
        for(int i=0;i<str.length();i++){
            buf.append(str.charAt(str.length()-1-i));
        }
        return buf.toString();
    }


}
class MainTest1{

    public static String stringOpts(StringFunc func,String str){
        return func.func(str);
    }

    public static void main(String[] args) {
        ObjRef objRef = new ObjRef();
        String result = stringOpts(objRef::reverse,"你好 lambda");
        System.out.println(result);
    }
}
//输出
//adbmal 好你
实例方法

className::methodName

  1. 第一个参数匹配调用对象
  2. 第二个参数匹配调用方法的参数

具体请看代码示例:

函数式接口

注意这个函数有两个参数

interface MyFunc<T>{
    boolean func(T t1,T t2);
}

实体对象

主要使用下面的equals,lessThan方法,两个方法中的参数对应函数式接口中的第二个参数

class Student{
    private Integer glades;

    public Student(Integer glades){
        this.glades = glades;
    }

    public boolean equals(Student student){
        return glades == student.glades;
    }

    public boolean lessThan(Student student){
        return glades < student.glades;
    }

}

方法引用

 public static <T> int count(T[] val,MyFunc<T> f,T v){
        int count = 0;
        for(int i=0;i<val.length;i++){
            if(f.func(val[i],v))
                count++;
        }
        return count;
    }

测试

  Student[] arrs = new Student[]{
      new Student(50),
      new Student(60),
      new Student(60),
      new Student(80),
      new Student(90)};

        int ret = count(arrs,Student::equals,new Student(60));
        System.out.println(ret);
//2
        int ret1 = count(arrs,Student::lessThan,new Student(60));
        System.out.println(ret1);
//2

泛型中引用

接口

interface MyFunc<T>{
    int func(T[] vals,T t);
}

泛型方法,非泛型类

public class FanxingLambda {
    static <T> int countMath(T[] vals,T t){
        int count = 0;
        for(int i=0;i<vals.length;i++){
            if(vals[i] == t)
                count++;
        }
        return count;
    }
}

引用方法

   public static <T> int countFun(MyFunc<T> f,T[] vals,T t){
        return f.func(vals,t);
    }

测试方法

    public static void main(String[] args) {
        Integer[] arrs = new Integer[]{1,2,3,4,5,2,4,5,2,1,2,3};
        int count =  countFun(FanxingLambda::<Integer>countMath,arrs,2);
        System.out.println(count);

    }

注意

int count =  countFun(FanxingLambda::<Integer>countMath,arrs,2);

FanxingLambda::countMath

因为FanxingLambda不是泛型类,但是countMath是泛型方法,所以可以在::前面指定Integer类型

也可以不写,因为类型参数会推断出类型

找出最大值示例

需要使用Collections.max方法,其中第二个参数传入一个比较器Comparator

源码

Collections :
public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp)  
Comparator:
int compare(T o1, T o2);

测试代码

实体

class Salary{
    private double val;
    public Salary(double val){
        this.val = val;
    }

    public double getVal(){
        return val;
    }

    public static int comparaSalary(Salary s1,Salary s2){
        return (int)(s1.val - s2.val);
    }
}

测试方法

   public static void main(String[] args) {
        List<Salary> list = new ArrayList<>();
        list.add(new Salary(100.1));
        list.add(new Salary(2000.3));
        list.add(new Salary(1000));
        list.add(new Salary(3000.5));
        list.add(new Salary(235));

        Salary s = Collections.max(list,Salary::comparaSalary);
        System.out.println(s.getVal());
    }
    
    //3000.5

构造函数引用

classname::new

interface ClassFun<T,V>{
    T func(V v);
}
class Emp{
    private Integer age;

    public Emp(Integer age){
        this.age = age;
    }
    public Integer getAge(){
        return age;
    }
}
class People<T>{
    private T t;
    public People(T t){
        this.t = t;
    }
    public T getVal(){
        return t;
    }
}
 ClassFun<Emp,Integer> c = Emp::new;
        Emp e = c.func(100);
        System.out.println(e.getAge());
        ClassFun<People<String>,String> c1 = People::new;
        People<String> p = c1.func("zhangsan");
        System.out.println(p.getVal());
        
        //100
		//zhangsan

你可能感兴趣的:(开发语言,java)