lamdba表达式(1)

lambda概念

jdk 1.8以后引入了lambda这一特性,其概念如下:
1、lamdba表达式也被称为箭头函数,匿名内部类,闭包。
2、体现的是轻量级的函数式编程思想。
3、’->’ 符号为核心符号即操作符号,左侧是所需要的传入的参数,右边是具体操作的数据。

lambda处理那些问题

1、实现了编码即数据(Model Codl as Data)尽量的将代码轻量封装起来。
2、处理了语法冗余,this关键字,变量捕获,数据控制不友好等问题,
3、lambda表达式不是新的技术,是对现有技术的语义优化方案,需要考虑实际的性能问题。
传统编码和lamdba的区别实例一:

public static void main(String[] args) {
        // 传统代码
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("传统模式下的多线程创建" +
                        Thread.currentThread().getName());
            }
        }).start();
        // 使用lambda 表达式
        new Thread(() -> {
            System.out.println("lambda--->thread" + Thread.currentThread().getName());
        }).start();
    }

函数式接口(function interface)

函数式接口。是指只包含一个操作方法,lambda表达式,也只能操作一个方法。java中lambda核心就是一个函数式接口打实现。
就是java系统中打接口,只包含一个接口方法的特殊接口。如

// @Functionallnterface 语义检查是否符合lambda语义规范
@FunctionalInterface
public interface CommonUtil {
    // 是否为空
    boolean isEmpty(String str);
}

除了抽象方法还可以包含静态方法及默认方法


@FunctionalInterface
public interface FunctionalInterfaceImpl {
    /**
     * 抽象方法
     *
     * @param arr
     * @return
     */
    String convertArr(String[] arr);

    /**
     * 默认方法
     *
     * @return Arr
     * @Param s
     */
    default String stringToArr(String s) {
        return null;
    }

    /**
     * 静态方法
     * @param s
     * @return
     */
    static boolean isEmpty(String s) {
        // 具体逻辑
        return false;
    }
}

除了抽象接口和默认方法及静态方法。由于函数式接口是java类型系统中的接口,所以间接的也就继承了Object类,所以实现Object的方法也是可以通过语义检查的。

@FunctionalInterface
public interface CommonUtil {
    // 是否为空
    boolean isEmpty(String str);

    // Object的方法
    int hashCode();

    boolean equals(Object obj);

    String toString();

}

java类型系统内见函数式接口

java 8以上在java.util.function提供了常用打函数式接口
以下都是提供函数是接口打功能
java.lang.Runable
java.lang.Comparabale
java.lang.Comparator
java.io.FileFilter
java.util.function.Predicate 接受参数T返回一个boolean值
Predicate源码

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

具体使用如:

  Predicate<String > res = (String str) -> {
            return str.equals("");
        };
        System.out.println(res.test("fb"));
        System.out.println(res.test(""));

java.util.function.Comsumer 接受参数T,不返回任何值
Comsumer源码

package java.util.function;
import java.util.Objects;
@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

使用实例如:

 Consumer<String> consumer = (String str) ->{
            System.out.println("传过来的参数为:" + str);
        };
        consumer.accept("paraemter");

java.util.function.Function<T,R> 接受一个T参数返回一个R结果

源码如下

/*
package java.util.function;
import java.util.Objects;
@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }


    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

使用实例:


        Function<Integer,String> function = (Integer para) -> {
            return para instanceof Integer ? "int" : "string";
        };

        System.out.println(function.apply(3));
        System.out.println(function.apply(9));

java.util.function.Supplier 不接收参数,提供对T类型的创建工厂

package java.util.function;
@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

java.util.function.UnaryOperator
接收参数T,返回一个T
java.util.function.BiFunction<T,U,R>接收两个参数T和U,返回一个R 结果

@FunctionalInterface
public interface BiFunction<T, U, R> 
    R apply(T t, U u);

java.util.function.BinaryOperator 继承了BiFunction<T,T,T>
接收两个参数T,返回一个T

@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> {
    
    public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) {
        Objects.requireNonNull(comparator);
        return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;
    }

    public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) {
        Objects.requireNonNull(comparator);
        return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
    }
}

java.utili.function.BiPredicate<T, U>接收两个参数类型返回一个boolean结果

@FunctionalInterface
public interface BiPredicate<T, U> {
    boolean test(T t, U u);
    default BiPredicate<T, U> and(BiPredicate<? super T, ? super U> other) {
        Objects.requireNonNull(other);
        return (T t, U u) -> test(t, u) && other.test(t, u);
    }

    default BiPredicate<T, U> negate() {
        return (T t, U u) -> !test(t, u);
    }
    default BiPredicate<T, U> or(BiPredicate<? super T, ? super U> other) {
        Objects.requireNonNull(other);
        return (T t, U u) -> test(t, u) || other.test(t, u);
    }
}

lambda基本使用

1 声明:就是和lambda表达式绑定接口类型
2 参数:在操作符号’->’ 左侧,在一个园括号中,和绑定打接口中的抽象方法的参数个数及顺序是一致。
3 操作符: lambda核心操作符 ‘->’
4 执行代码块:在操作符的右侧,包含一对大括号中。
语法如 :[接口声明] = (参数)-> {执行代码块}

变量访问操作

1 匿名内部类
全局变量和局部变量和内部变量
全局变量 直接直接访问,局部变量也是可以的,但是局部变量不能修改,默认推导修饰符使用的
this关键字表示的是当前内部类,对当前内部类的访问可以使用this.内部变量,但是不能修改。

2 lambda表达式

this关键字,表示的就是所属方法在所在类型的对象。既可以访问也可以修改。
同样局部变量也可直接访问但是不能修改。
内部变量可以直接修改。

public class ThisMain {
    // 全局变量
    String str1 = "全局变量";

    public void innerClass() {
        // 局部变量
        String str2 = "局部变量";

        new Thread(new Runnable() {
            // 内部变量
            String str3 = "内部变量";

            @Override
            public void run() {
                System.out.println(str1); // this表示当前内部类型的对象 
                str3 = "f";
                System.out.println(str2); // 可以访问,但是不可以修改
                System.out.println(this.str3);
                System.out.println(str3);
            }
        }).start();
    }

    public void lambdaThis() {
        String str2 = "局部变量";
        new Thread( () -> {
            String str3 = "内部类型的变量";
            System.out.println(this.str1); // 此时的this 关键字为 所属的方法所在类型的对象
            System.out.println(str1);
            System.out.println(str2); // 不能修改,默认的类型推导的修饰符为final
            System.out.println(str3);
        }).start();
    }

    public static void main(String[] args) {
        ThisMain main = new ThisMain();
        main.innerClass();
        main.lambdaThis();
    }
}

lambda表达式类型检查
类型检查包括:

  • 表达式的类型检查
  • 参数类型检查
    如下实例:
public class MainDemo {

    public static void test(ListUtils<String, List> para) {
        List<String> res = para.add("参数", new ArrayList<>());
        System.out.println(res);
    }

    public static void main(String[] args) {

        test(new ListUtils<String, List>() {
            @Override
            public List add(String s, List list) {
                list.add(s);
                return list;
            }
        });
        // 使用lambda表达
        test((x, y) -> {
            y.add(x);
            return y;
        });
    }
}

@FunctionalInterface
interface ListUtils<R, T> {
    T add(R r, T t);
}

lambda表达式对方法重构表达式的影响
通过一段代码观察lambda对方法重构的影响

public class App {

    interface Param1{
        void method(String param);
    }

    interface Param2{
        void method(String param);
    }

    public void lambdaMethod(Param1 param) {
        param.method("重构方法一");
    }

    public void lambdaMethod(Param2 param) {
        param.method("重构方法二");
    }
    public static void main(String[] args) {
        App app = new App();
        // 匿名内部类一(Param1)
        app.lambdaMethod(new Param1() {
            @Override
            public void method(String param) {
                System.out.println(param);
            }
        });
        // 匿名内部类二(Param2)
        app.lambdaMethod(new Param2() {
            @Override
            public void method(String param) {
                System.out.println(param);
            }
        });

        /**
         * lambda表达式在类型检查会自动推导目标类型
         * lambdaMethod() -> 方法 -> 重构方法
         * -> Param1 函数式 接口
         * -> Param2 函数式接口
         * 调用方法 -> 传递lambda表达式 -> jvm自动类型推导 -> Param1 或 Param2
         * 然后出现混淆的
         */
         // 编译不通过
        app.lambdaMethod(() -> System.out.println());

    }
}

对于重构方法lambda在类型检查自动推导目标类型 ,然后对于重构方法容易导致目标类型出现混淆的问题,所以存在重构方法是尽量使用匿名内部类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值