lambda表达式入门到实践

lambda表达式

Java 8 加入的新特性,lambda表达式是一个可传递的代码块,可以在以后执行一次或多次.在接口只有一个方法时,以表达式的形式简写接口的实列代码.说起来有点抽象,可以理解为让代码少写几行.

格式

参数,箭头(->)以及一个表达式

-> : lambda 操作符

左边: 接口方法的形参

右边: 方法体

使用

对于只有一个抽象方法的接口,需要这种接口的对象时,就可以提供一个lambda表达式。这种接口称为函数式接口(functional interface)。

常见函数式接口

之前已有的函数式接口:

  • java.lang.Runnable
@FunctionalInterface
public interface Runnable {
    public abstract void run();
}
  • java.util.Comparator
@FunctionalInterface
public interface Comparator<T> {
    int compare(T o1, T o2);
}

java 8 新增函数式接口:

可以自己去java.util.function下查看

  • java.util.function.Consumer

用来消费某个实例

@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);
}
  • java.util.function.Supplier

用来创建某个实例

@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}
  • java.util.function.Predicate

进行断言操作

@FunctionalInterface
public interface Predicate<T> {

    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);
}
  • java.util.function.Predicate

函数的运用

@FunctionalInterface
public interface Function<T, R> {

    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);

}

示例

通过示例代码展示lambda表达式的使用

1.Consumer接口

 @Test
    public void consumerTest() {
        //需求,打印传入的String字符串
        //1.传统方式的使用,使用内部类的方式
        Consumer<String> consumer1 = new Consumer<String>() {
            @Override
            public void accept(String s) {
                //执行逻辑...
                System.out.println(s);
            }
        };
        //调用
        consumer1.accept("传统方式");


        //2.使用完整lambda方式
        //只需要方法的参数和方法体,通过-> 符号连接
        Consumer<String> consumer2 = (String s) -> {
            //执行逻辑...
            System.out.println(s);
        };
        //调用
        consumer2.accept("完整lambda方式");

        //3.参数部分简写,  Consumer<String> 部分已经定义了参数类型,所以形参的类型可以去掉
        //当只有一个参数时,,可以去掉括号
        Consumer<String> consumer3 =  s -> {
            //执行逻辑...
            System.out.println(s);
        };
        //调用
        consumer3.accept("简写参数");

        //4.简写大括号
        //当方法体中只有一行代码时,可以去掉大括号
        Consumer<String> consumer4 =  s -> System.out.println(s);

        //调用
        consumer4.accept("最终写法");

    }

1.Supplier接口

    @Test
    public void supplierTest() {
        //需求:获取最大的Integer值
        //1.传统方式的使用,使用内部类的方式
        Supplier<Integer> supplier1 = new Supplier() {
            @Override
            public Object get() {
                //执行逻辑...
                return Integer.MAX_VALUE;
            }
        };
        //调用
        Integer integer1 = supplier1.get();
        System.out.println(integer1);

        //2.使用完整lambda方式
        //等号左边不变
        //等号右边,只需要方法的参数和方法体,通过-> 符号连接
        //没有参数时,就使用空括号
        //不需要返回值,lambda会自己推导
        Supplier<Integer> supplier2 =() -> Integer.MAX_VALUE;
        Integer integer2 = supplier2.get();
        System.out.println(integer2);
    }

3.Predicate接口

   @Test
    public void predicateTest() {
        //需求:判断传入数值是否等于0
        //1.传统方式的使用,使用内部类的方式
        Predicate<Integer> predicate1 = new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                return integer == null ? false : integer.equals(0);
            }
        };
        //调用
        System.out.println(predicate1.test(null));

        //2.使用完整lambda方式
        //等号左边不变
        //等号右边,只需要方法的参数和方法体,通过-> 符号连接
        //只有一个参数时,去掉括号
        //不需要返回值,lambda会自己推导
        Predicate<Integer> predicate2 = integer -> integer == null ? false : integer.equals(0);
        System.out.println(predicate2.test(0));
    }

4.Function接口

  @Test
    public void functionTest() {
        //需求:传入一段英文字符串,返回大写的字符串
        //1.传统方式的使用,使用内部类的方式
        Function<String, String> function1 = new Function<String, String>() {
            @Override
            public String apply(String s) {
                return s == null ? null : s.toUpperCase();
            }
        };
        //调用
        System.out.println(function1.apply("abc"));

        //2.使用完整lambda方式
        //等号左边不变
        //等号右边,只需要方法的参数和方法体,通过-> 符号连接
        //只有一个参数时,去掉括号
        //不需要返回值,lambda会自己推导
        Function<String, String> function2 = s -> s == null ? null : s.toUpperCase();
        System.out.println(function2.apply("lambda"));
    }

补充

方法引用

有时,可能已经有现成的方法可以完成你想要传递到其他代码的某个动作。

可以通过下面三种方式进行方法引用,很多人就说了,对象直接掉方法,直接用.就行了,还用::,又有人说了类掉静态方法很好理解,类调静态方法又是怎么回事?

  • object::instanceMethod

通过对象::调用方法

  • Class::staticMethod

通过类::调用静态方法

  • Class::instanceMethod

通过类:: 非静态方法

在前2种情况中,方法引用等价于提供方法参数的lambda表达式。

举列子说明
1.对象::方法

    @Test
    public void methodTest1() {
        //需求:打印传入的String字符串
        //lambda写法
        Consumer<String> consumer1 = s -> System.out.println(s);
        //调用
        consumer1.accept("lambda写法");

        //分析,其实就是传入了一个字符串,然后调用了System中PrintStream中的println方法
        //是不是可以直接抵用呢,对象方法
        //PrintStream printStream = System.out;
         //参数就是传入值,参数都省略
        Consumer<String> consumer2=System.out::println;
        consumer2.accept("对象::方法");
    }

2.类::静态方法

    @Test
    public void methodTest2() {
        //需求:传入一个对象,将对象转化String类型
        //lambda写法
        Function<Object, String> function1=o -> String.valueOf(o);
        //调用
        System.out.println(function1.apply(1l));

        //valueOf方法是String中的静态方法,可以直接通过String类来调用
        //传入参数为valueOf方法所需参数,省略
        Function<Object, String> function2=String::valueOf;
        System.out.println(function2.apply(2l));
    }

2.类::非静态方法

这种用起来是有条件的,第1个参数会成为方法的目标。例如,String::compareToIgnoreCase等同于(x,y)->x.compareToIgnoreCase(y)。

这里以Comparator接口为例


@FunctionalInterface
public interface Comparator<T> {
    int compare(T o1, T o2);
}

    @Test
    public void methodTest3() {
         //需求:比较两个字符
        //lambda写法
        Comparator<String> comparator1=(s1,s2)-> s1.compareToIgnoreCase(s2);
        //调用
        System.out.println(comparator1.compare("a","A"));

        //因为使用了String中的compareToIgnoreCase方法,s1.compareToIgnoreCase(s2)可以简写成String::compareToIgnoreCase
        Comparator<String> comparator2=String::compareToIgnoreCase;
        //调用
        System.out.println(comparator2.compare("a","b"));
    }

总结

  • 除了构造器引用外,lambda表达式的语法已经讲完了.有兴趣的话可以自行了解构造器引用,与方法引用的方式差不多.
  • lambda语法不复杂,就是一个熟悉的过程.没有必要非要用lambda表达式.匿名内部类的方式是必须要会的,lambda要能看得懂.
  • lambda让代码更简洁,Stream API 中会用到
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值