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 编程时所采用的标准接口
来源: http://www.bubuko.com/infodetail-2899936.html