菜鸡的Java笔记 第三十六 StudyLambda

StudyLambda
    Lambda 指的是函数式编程,现在最为流行的编程模式为面向对象,很多的开发者并不认可面向对象,所以很多的开发者宁愿继续使用 C 语言进行开发,也不愿意使用java,c++
    但是随着整个行业的技术发展,函数编程语言已经开始被很多的人所认可,于是java也是被迫环境因素追加了 Lambda
    如果要想去理解 Lambda 表达式设置的背景,就需要首先理解匿名内部类
    匿名内部类解决的问题:对于抽象类或接口的子类如果发现其只使用一次,那么就没有必要将其定义为一个类,这样可以节约类的定义空间,但是匿名内部类太麻烦了
    
    范例:观察匿名内部类

package cn.mysterious;
interface IMessage{
    public String getMsg();
    
}

public class Lang0 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        IMessage msg = new IMessage() {
            
            @Override
            public String getMsg() {
                // TODO Auto-generated method stub
                return "ssssssssssssssss";
            }
        };
        System.out.println(msg.getMsg());
    }

}

           
            因为面向对象的最大特征:结构要完整,这个时候如果使用 Lambda 表达式呢?
            

package cn.mysterious;
interface IMessage{
    public String getMsg();
    
}

public class Lang0 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        IMessage msg = () ->"?????????";
        System.out.println(msg.getMsg());
    }
}

           
            一个简单的一行语句就代替了完整的结构,那么自然会有许多的追捧者去使用它
            实际上 Lambda 表达式以上的做法只是其中的一种形式,它有三种语法:
                () ->{多行语句,return 语句};
                () ->单行语句;
                () ->返回结果;
                
            范例:多行语句定义

package cn.mysterious;
interface IMessage{
    public String getMsg();
    
}

public class Lang0 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        IMessage msg = () ->{
            String str = "???????";
            return str;
        };
        System.out.println(msg.getMsg());
    }

}                

               
                如果现在设计的接口里面没有返回值的存在,那么方法体也可以使用一行语句,可以直接避免“{}”定义

package cn.mysterious;
interface IMessage{
    public void print();
    
}

public class Lang0 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        IMessage msg = () -> System.out.println("???????????");;
        msg.print();
    }

}

               
            如果要想使用 Lambda 表达式有一个重要的前提:一个接口之中只允许有一个抽象方法,如果你现在需要强制描述接口定义(某一个接口就是函数式编程接口)则可以追加一个注解

package cn.mysterious;
@FunctionalInterface // 是函数式接口,只允许有一个抽象方法
interface IMessage{
    public void print();
    
}
public class Lang0 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        IMessage msg = () -> System.out.println("???????????");;
        msg.print();
    }

}

               
                Lambda 是基于函数式接口定义的,如果要想使用 Lambda  重要的前提:一个接口之中只允许有一个抽象方法
                
            如果有很多抽象方法呢?

package cn.mysterious;
@FunctionalInterface // 是函数式接口,只允许有一个抽象方法
interface IMessage{
    public void print();
    public default void fun(){}
    
}
public class Lang0 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        IMessage msg = () -> System.out.println("???????????");;
        msg.print();
        msg.fun();
    }

}


*/

/*    
    在之前所学习的都属于对象的引用,对象引用的本质在于:同一块堆内存空间,可以被不同的栈内存所指向
    那么方法的引用指的是一个方法可以设置不同的别名,即:可以被不同的接口的对象所使用
    对于方法的引用在java里面提供有四种处理形式:
        引用类中的静态方法:类名称 :: static 方法名称
        引用某个对象的方法;实例化对象 :: 普通方法
        引用某个特定的方法:类名称 :: 普通方法
        引用构造方法:类名称 :: 普通方法
        
    范例:引用静态方法
        String 类有一个 valueOf() 方法,该方法可以将接收到的基本数据类型变为字符串
            方法定义: public static String valueOf(数据类型 变量);
            

package cn.mysterious;
/**
 * 进行以函数式接口定义
 * @author mldn
 * @param <P> 引用方法的参数类型
 * @param <R> 引用方法的返回值定义
 */
@FunctionalInterface // 是函数式接口,只允许有一个抽象方法
interface IUtile<P,R>{
    public R convert(P p); // 做新的方法
    
}
public class Lang0 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        IUtile<Integer,String> objA = String :: valueOf; // 方法引用
        System.out.println(objA.convert(100));
    }

}

           
        也可以使用 Integer,parseInt() 转换
            

package cn.mysterious;
public class Lang0 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        IUtil<Integer,String> objA =  String :: valueOf; // 方法引用
        System.out.println(fun(objA,100).length());
    }
    public static <P,R> R fun(IUtil<P,R> temp,P p){
        return temp.convert(p);
    }

}
/**
 * 进行以函数式接口定义
 * @author mldn
 * @param <P> 引用方法的参数类型
 * @param <R> 引用方法的返回值定义
 */
@FunctionalInterface // 是函数式接口,只允许有一个抽象方法
interface IUtil<P,R>{
    public R convert(P p); // 做新的方法
    
}

           
        以上只是引用了一个简单的 static 方法,也可以直接引用某一个类中的方法
        
        范例:引用 String 类中的字符串转大写方法
            [“字符串”.toUpperCase] public String toUpperCase();

package cn.mysterious;

@FunctionalInterface // 是函数式接口,只允许有一个抽象方法
interface IUtil<R>{
    public R upper(); // 做新的方法
    
}
public class Lang0 {

    public static void main(String[] args) {
        IUtil<String> obj = "hello" :: toUpperCase;
        System.out.println(obj.upper());
    }
}

           
        范例:引用类中的普通方法
            String 类有一个 compareTo() 方法,这个方法是一个普通方法,而且需要两个参数比较
                方法: public int compareTo(String str);

package cn.mysterious;

@FunctionalInterface // 是函数式接口,只允许有一个抽象方法
interface IUtil<R,P>{
    public R compare(P p1,P p2); // 做新的方法
    
}
public class Lang0 {

    public static void main(String[] args) {
        IUtil<Integer,String> obj = String :: compareTo;
        System.out.println(obj.compare("A","a"));
    }
}

               
            以上使用的都是类的结构,而整个设计里面最大的亮点在于构造方法也可以设置别名引用
            
        范例:引用构造方法

package cn.mysterious;
@FunctionalInterface // 是函数式接口,只允许有一个抽象方法
interface IUtil<R,FP,SP>{
    public R create(FP p1,SP p2); // 做新的方法

    
}
public class Lang0 {

    public static void main(String[] args) {
        IUtil<Member,String,Integer> obj = Member :: new; // 引用构造
        System.out.println(obj.create("????",20));
    }

}
class Member{
    private String name;
    private int age;
    public Member(String name,int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "Member [name=" + name + ", age=" + age + "]";
    }
}

           
            Lambda 表达式的操作除了可以自定义方法体之外,用户也可以去引用已经实现好的类中的方法
            
    
    内建函数式接口
        函数式接口是 Lambda 实现关键所在,但是很多时候如果要想进行一个项目设计的时候,肯定需要许多标准的函数式接口
        所以在java设计过程之中考虑到用户使用标准型问题,所以也提供有四个内建的函数式接口
            功能性函数接口: public Interface Function<T,R>{R apply(T t)}
            消费型函数接口: public interface Consumer<T>{public void accept(T t)}
            供给性函数接口: public interface Supplier<T>{public T get()}
            断言型函数接口: public interface Predicate<T>{public boolean test(T t)}
            
        范例:使用功能型接口

    package cn.mysterious;

    import java.util.function.Function;

    public class Lang0 {

        public static void main(String[] args) {
            Function<Integer,String> obj = String :: valueOf;
            System.out.println(obj.apply(100));
        }

    }

           
        实际上在 java.util.function 开发包里面有许多扩展的函数式接口,可以帮助用户简化定义
        
        范例:使用 IntFunction

    package cn.mysterious;

    import java.util.function.IntFunction;
    public class Lang0 {

        public static void main(String[] args) {
            IntFunction<String> obj = String :: valueOf;
            System.out.println(obj.apply(100));
        }

    }

           
        范例:消费型接口,现在学习到的消费处理只有一个方法:打印输出

    package cn.mysterious;

    import java.util.function.Consumer;
    import java.util.function.IntFunction;
    public class Lang0 {

        public static void main(String[] args) {
            Consumer<String> obj = System.out :: println;
            obj.accept("?????");
        }

    }

           
        范例:供给型,字符串转大写或小写(“Hello” .toLowerCase())

    package cn.mysterious;

    import java.util.function.Supplier;

    public class Lang0 {

        public static void main(String[] args) {
            Supplier<String> obj = "Hello" :: toLowerCase;
            System.out.println(obj.get());

        }

    }

           
        范例:断言型接口( startsWith() 方法,返回boolean,接收一个字符串)

    package cn.mysterious;

    import java.util.function.Predicate;

    public class Lang0 {

        public static void main(String[] args) {
            Predicate<String> obj = "##hello" :: startsWith;
            System.out.println(obj.test("##"));
        }

    }

           
            如果不去考虑标准,这些接口完全可以自己来实现,而这四个接口是 java 中进行 Lambda 编程时所采用的标准接口

            
   

猜你喜欢

转载自www.cnblogs.com/mysterious-killer/p/10123623.html