Java 8 新特性:Lambda 表达式与 Stream 流,重构你的编码效率(上篇:Lambda 表达式)

前言

接口中默认方法修饰为普通方法

在jdk8之前,interface之中可以定义变量和方法,变量必须是publicstaticfinal的,方法必须是publicabstract的,由于这些修饰符都是默认的。

接口定义方法:public 抽象方法 需要子类实现
接口定义变量:publicstaticfinal

在JDK 1.8开始 支持使用staticdefault 修饰 可以写方法体,不需要子类重写。
方法:

  1. 普通方法:可以有方法体
  2. 抽象方法:没有方法体需要子类实现重写。

示例代码

public interface JDK8Inerface {
    /**
     * 默认就是 public、abstract
     */
    void add();

    /**
     * jdk8 提供了  default 关键字 用它修饰的方法(默认方法)可以写方法体
     */
    default void defaultGet(){
        System.out.println("defaultGet");
    }
    static void staticDel(){
        System.out.println("staticDel");
    }
}

public class JDK8InerfaceImpl implements JDK8Inerface {
   /**
    * 定义子类实现 JDK8Inerface 没有强制要求重写 default 和静态方法
    */
   @Override
   public void add() {
       System.out.println("add");
   }
}

public class Test01 {
   public static void main(String[] args) {
       JDK8InerfaceImpl jdk8InerfaceImpl = new JDK8InerfaceImpl();
       jdk8InerfaceImpl.add();//对象.方法名称
       jdk8InerfaceImpl.defaultGet();//对象.方法名称
       JDK8Inerface.staticDel();//类名.静态方法名称
   }
}

Lambda表达式

什么是Lambda表达式
LAMBADA 好处: 简化我们匿名内部类的调用。
Lambda+方法引入 代码变得更加精简。

Lambda 表达式(lambda expression)是一个匿名函数,简化我们调用匿名函数的过程。

为什么要使用Lambda表达式
可以非常简洁的形式调用我们的匿名函数接口。

示例代码

public interface OrderService {
   void get();
   /**
    * 如果需要用到 OrderService 接口
    * 接口是无法 new 出来的
    * 可以通过匿名内部类 new 出来他
    */
}

public class Test01 {
   public static void main(String[] args) {
       /**
        * 匿名内部类 创建一个(匿名)子类 用父类接收
        * 创建了一个 OrderService 对象的匿名实现,并重写了其 get 方法。在重写的 get 方法中,打印了 “get”。
        * 最后通过调用 orderService.get() 来执行该方法,并输出 “get”。
        *
        * 这种使用匿名实现类的方式可以方便地在需要自定义行为的情况下,创建临时的实现对象。
        * 可以根据具体需求,在匿名实现类中重写需要的方法,并在需要时调用相应的方法
        */

       OrderService orderService = new OrderService() {
           @Override
           public void get() {
               System.out.println("get");
           }
       };
       orderService.get();
       System.out.println("-------------");
       new OrderService() {
           @Override
           public void get() {
               System.out.println("get");
           }
       }.get();
       System.out.println("-----Lambda表达式--------");
       ((OrderService) () -> System.out.println("get")).get();
   }
}

1.Lambda表达式的规范

使用Lambda表达式 依赖于函数接口
1.在接口中只能够允许有一个抽象方法
2.在函数接口中定义object类中方法
3.使用默认或者静态方法
4.@FunctionalInterface 表示该接口为函数接口

Java中使用Lambda表达式的规范,必须是为函数接口
函数接口的定义:在该接口中只能存在一个抽象方法,该接口称作为函数接口

Java中的Lambda表达式的规范,必须是为函数接口。
函数接口的定义:在该接口中只能存在一个抽象方法,该接口称作为函数接口

JDK中自带的函数接口:
java.lang.Runnable
java.util.concurrent.Callable
java.security.PrivilegedAction
java.util.Comparator
java.io.FileFilter
java.nio.file.PathMatcher
java.lang.reflect.InvocationHandler
java.beans.PropertyChangeListener
java.awt.event.ActionListener
javax.swing.event.ChangeListener
我们也可以使用@FunctionalInterface修饰为函数接口

函数接口定义

  1. 在接口中只能有一个抽象方法
  2. @FunctionalInterface 标记为该接口为函数接口
  3. 可以通过default 修饰为普通方法
  4. 可以定义object类中的方法

示例代码

@FunctionalInterface//这个注解标记的接口被称为函数式接口
public interface MyFunctionalInterface {
    void get();

    default void defaultAdd() {
        System.out.println("我是默认的方法");
    }

    /**
     * Object 父类中的方法可以在函数中调用
     */
    String toString();
}

2.Java系统内置那些函数接口

消费型接口

	Conusmer<T>
	       void accept(T t);
	BiConusmer<T,U>
	       void accept(T t,U u);//增加一种入参类型

供给型接口

	Supplier<T>
	       void get();

函数型接口

	Function<T ,R>
	       R apply(T t);
	UnaryOperator<T>
	       T apply(T t);//入参与返回值类型一致
	BiFunction <T ,U,R>
	       R apply(T t,U u);//增加一个参数类型
	BinaryOperator<T>
	       T apply(T t1,T t2);//l两个相同类型入参与同类型返回值
	ToIntFunction<T>//限定返回int
	ToLongFunction<T>//限定返回long
	ToDoubleFunction<T>//限定返回double
	IntFunction<R>//限定入参int,返回泛型R
	LongFunction<R>//限定入参long,返回泛型R
	DoubleFunction<R>//限定入参double,返回泛型R

断言型接口

	Predicate<T>
	       boolean test(T t);

3.Lambda基础语法

	()---参数列表
	 -> 分隔
	{}   方法体
	(a,b)->{
	}

无参方法调用
带参数方法调用

	(函数接口的参数列表 不需要写类型只需要定义参数名称)->{方法体}
	
	():函数方法参数列表
	->分隔 {}方法体
	(a,b)->{
	Sout(a,b)
	}

Lambda语法:

():参数列表
->分隔
{}:方法体
()->{}

示例代码

无参方法调用

@FunctionalInterface
public interface AcanthopanaxInterface {
   void get();
}
public static void main(String[] args) {
   //使用匿名内部类调用
   new AcanthopanaxInterface() {
       @Override
       public void get() {
           System.out.println("get");
       }
   }.get();
   System.out.println("-----------");
   AcanthopanaxInterface acanthopanaxInterface = () -> {
       System.out.println("使用lamdba表达式调用方法");
   };
   acanthopanaxInterface.get();
}

带参数和返回值

@FunctionalInterface
public interface YouShenInterface {
   String get(int i, int j);
}
public static void main(String[] args) {
   //使用匿名内部类调用
   YouShenInterface youShenInterface = new YouShenInterface() {
       @Override
       public String get(int i, int j) {
           return i + "---" + j;
       }
   };
   System.out.println(youShenInterface.get(1, 2));
   System.out.println("-----------");
   //2.使用lamdba 调用有参数函数方法
   YouShenInterface youShenInterface2 = (i, j) -> {
       return i + "--" + j;
   };
   System.out.println(youShenInterface2.get(1, 2));
}

精简语法
如果方法体中只有一条语句的情况下 可以不需要写{}
如果方法体只有一条return的情况下不需要些{} 和return

	((AcanthopanaxInterface)()-> System.out.println("get")).get();
	String reult = ((YouShenInterface) (i, j) -> i + "-" + j).get(1, 2);
	System.out.println(reult);

4.方法引入

什么是方法引入
方法引入:需要结合lambda表达式能够让代码变得更加精简。

  1. 匿名内部类使用
  2. Lambda调用匿名内部类
  3. 方法引入

方法引入
1. 静态方法引入 类名::(静态)方法名称
2. 对象方法引入 类名:: 实例方法名称
3. 实例方法引入 new对象 对象实例::方法引入
4. 构造函数引入 类名::new

需要遵循一个规范:方法引入 方法参数列表、返回类型与函数接口参数列表与返回类型必须
要保持一致。

Lambda: 匿名内部类使用代码简洁问题。

类型语法对应lambda表达式
构造器引用Class::new(args) -> new 类名(args)
静态方法引用Class::static_method(args) -> 类名.static_method(args)
对象方法引用Class::method(inst,args) -> 类名.method(args)
实例方法引用instance::method(args) -> instance.method(args)

方法引用提供了非常有用的语法,可以直接引用已有的java类或对象的方法或构造器。方法引用其实也离不开Lambda表达式,
与lambda联合使用 ,方法引用可以使语言的构造更加紧凑简洁,减少冗余代码。

方法引用提供非常有用的语法,可以直接引用已有的java类或者对象中方法或者构造函数,
方法引用需要配合Lambda表达式语法一起使用减少代码的冗余性问题。

构造器引入
静态方法引入
对象方法引入
实例方法引入

1.方法引入规则

方法引入实际上就是lambda表达式中直接引入的方法。

必须遵循规范:引入的方法参数列表返回类型必须要和函数接口参数列表、返回
类型保持一致。

2.静态方法引入

示例代码
public class MethodReference {
    public static void main(String[] args) {
        // 1.使用匿名内部类的形式 调用get方法
//        new MessageInterface() {
//            @Override
//            public void get() {
//                MethodReference.getMethod();
//            }
//        }.get();
        MessageInterface messageInterface2 = () -> {
            MethodReference.getStaticMethod();
        };
        messageInterface2.get();
        // 使用方法引入调用方法 必须满足:方法引入的方法必须和函数接口中的方法参数列表/返回值一定保持一致。
        MessageInterface messageInterface = MethodReference::getStaticMethod;
        messageInterface.get();
    }

    /**
     * 静态方法引入
     */
    public static void getStaticMethod() {
        System.out.println("我是 getMethod");
    }
}}
@FunctionalInterface
public interface MessageInterface {
    void get();
}

3.对象方法引入

示例代码
public class Test23 {
    public static void main(String[] args) {
        // 1.使用匿名内部类的形式
//        MayiktService mayiktService = new MayiktService() {
//            @Override
//            public String get(Test23 test23) {
//                return test23.objGet();
//            }
//        };
//        System.out.println(mayiktService.get(new Test23()));
        // 2.Lambda
//        MayiktService mayiktService = (test23) -> test23.objGet();
//        System.out.println(mayiktService.get(new Test23()));
        // 3.方法引入 在这时候我们函数接口 第一个参数传递test23 返回调用test23.objGet方法
//        MayiktService mayiktService = Test23::objGet;
//        System.out.println(mayiktService.get(new Test23()));
        //Test23::objGet;----- (test23) -> test23.objGet();
        //   R apply(T t); T  apply方法传递的参数类型 : R apply 方法返回的类型
        // 需要将string类型字符串获取长度
//        Function<String, Integer> strFunction = (str) -> {
//            return str.length();
//        };
        Function<String, Integer> function2 = String::length;
        System.out.println(function2.apply("mayikt"));
    }

    public String objGet() {
        return "mayikt";
    }
}

4.实例方法引入

示例代码
public class Test009 {
    public static void main(String[] args) {
        //1.匿名内部类的写法
        Test009 test009 = new Test009();
//        MessageInterface messageInterface = new MessageInterface() {
//            @Override
//            public void get() {
//                test009.get();
//            }
//        };
//        messageInterface.get();
//        MessageInterface messageInterface = () -> {
//            test009.get();
//        };
//        messageInterface.get();
        MessageInterface messageInterface = test009::get;
        messageInterface.get(1);
    }

    public void get(Integer a) {
        System.out.println("方法引入get方法:" + a);
    }

@FunctionalInterface
public interface MessageInterface {
    void get(Integer a);
}

5.构造函数引入

示例代码
public class Test011 {
    public static void main(String[] args) {
//        UserInterface userInterface = () -> new UserEntity();
        UserInterface UserInterface2=  UserEntity::new;;
        UserInterface2.getUser();
    }
}
public class UserEntity {
    private String userName;
    private int age;

    public UserEntity() {

    }
public interface UserInterface {
    UserEntity getUser();
}

5.Lambda实战案例

1. Foreach 遍历集合

示例代码
public static void main(String[] args) {
        ArrayList<String> strings = new ArrayList<>();
        strings.add("赵立");
        strings.add("樊靖");
        strings.add("杨文琦");
        strings.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
        System.out.println("------------");
        strings.forEach((a)->System.out.println(a));
    }

2.Lambda集合排序

示例代码
public static void main(String[] args) {
   ArrayList<UserEntity> userEntities = new ArrayList<>();
   userEntities.add(new UserEntity("zhaoli", 1));
   userEntities.add(new UserEntity("fanjing", 5));
   userEntities.add(new UserEntity("zhangshan", 4));
   userEntities.add(new UserEntity("lisi", 3));
   System.out.println("排序前");
   userEntities.forEach((u) -> System.out.println(u));
   System.out.println("排序后");
   userEntities.sort(new Comparator<UserEntity>() {
       @Override
       public int compare(UserEntity o1, UserEntity o2) {
           return o1.getAge() - o2.getAge();
       }
   });
   userEntities.forEach((u) -> System.out.println(u));
}
public static void main(String[] args) {
   ArrayList<UserEntity> userEntities = new ArrayList<>();
   userEntities.add(new UserEntity("zhaoli", 1));
   userEntities.add(new UserEntity("fanjing", 5));
   userEntities.add(new UserEntity("zhangshan", 4));
   userEntities.add(new UserEntity("lisi", 3));
   System.out.println("排序前");
   userEntities.forEach((u) -> System.out.println(u));
   System.out.println("排序后");
   userEntities.sort((u1, u2) -> u1.getAge() - u2.getAge());
   userEntities.forEach((u) -> System.out.println(u));
}

3.线程调用

示例代码
public static void main(String[] args) {
   new Thread(new Runnable() {
       @Override
       public void run() {
           System.out.println("获取到线程名称:" + Thread.currentThread().getName() + ",子线程");
       }
   }).start();
   new Thread(()->System.out.println("获取到线程名称:" + Thread.currentThread().getName() + ",子线程")).start();
}

相关文章:
《Java 8 新特性:Lambda 表达式与 Stream 流,重构你的编码效率(下篇:stream流)》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值