java8之lambda表达式

lambda表达式是java8提供了一个比较重要的新特性之一,简化了很多代码的编写。

1、先看一个简单的例子,不是用lambda表达式创建一个线程:

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello world");
            }
        });

在Thread构造函数内传入一个Runnable接口的实现类。

2、再看一下使用lambda表达式创建线程的例子:

        Thread thread1 = new Thread(()->{
            System.out.println("hello world");
        });

使用lambda表达式以后回省略很多代码,不用再去重复的写要实现的方法名称,当然并不是所有的接口都能使用lambda表达式,必须要是函数式接口才能使用lambda。

函数式接口

有且只有一个抽象方法的接口被称为函数式接口。

函数式接口可以显示的被@FunctionalInterface所修饰,当被标识的接口不满足规定时,编译器会报错。

例:

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

lambda表达式的转换方式

//下面是三个自定义的函数式接口
interface T1{
    void say(int a);
}
interface T2{
    String say(int a);
}
interface T3{
    int say(int a,int b,int c);
}

    //()里面的数据表示参数,后面跟一个箭头->,最后面是大括号{}
    Runnable runnable = ()->{
        System.out.println("hello world");
    };
    //当参数只有一个时,可以省去()
    T1 t1 = a->{
        System.out.println("hi");
    };
    //当方法体只有一行时,可以省去{}
    T1 t2 = a-> System.out.println("hi");
    //有返回值的方法
    T2 t21 = (a)->{
        return a+"hi";
    };
    //同样的,方法体只有一行时,可以省略{},并且省略return
    T2 t22 = a -> a+ "hi";
    //有多个参数的方法,只需要在()内写上参数就行,并不需要写参数类型,因为lambda会自己推断参数类型,
    T3 t3 = (a,b,c)-> a + b + c;

使用lambda在实际项目开发者确实能省略很多的代码,比如在使用线程池处理线程,使用Comparable进行比较等等。

Java8内置的函数式接口

Java8提供了一个java.util.function包,包含了很多函数式接口,下面是最为基本也是最常用的4个,这四个函数式接口在我上一篇说stream的时候基本上都提到过,所以下面只是列出以下代码并做一个简单的说明,就不再去写例子了,有兴趣的可以自己去写一些实现类去了解一下,都是非常简单的接口,这些接口在stream里面用到的非常多。

Function接口:

@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接口的唯一抽象方法是apply,作用是接收一个指定类型的参数,返回一个指定类型的结果

Consumer接口

@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接口中accept方法的作用是接收指定参数类型,无返回值,重点在于内部消费

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中的test方法,传入指定类型参数,返回布尔类型的结果,用于判断,断言

Supplier接口:

@FunctionalInterface
public interface Supplier<T> {

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

Supplier意为供应,只有一个方法get,不接收任何参数,只返回指定类型结果。

 

posted @ 2019-09-01 17:06  卫旗  阅读(377)  评论(0编辑  收藏  举报