Java Lambda 表达式。

Java Lambda 表达式。



~

在这里插入图片描述



what。

  • Lambda 表达式也被称为箭头函数、匿名函数、闭包。
  • Lambda 表达式体现的是轻量级函数式编程思想。
  • -> 符号式 Lambda 表达式核心操作符号, 符号左侧是操作参数,符号右侧是操作表达式。
  • jdk8 新特性。


Model Code As Data。
  • Model Code as Data,编码及数据,尽可能轻量级的将代码封装为数据。
  • 解决方案:接口 & 实现类(匿名内部类)。
  • 令存在问题:语法冗余、this 关键字、变量捕获、数据控制等。


需求。

线程类的创建。

解决方案:匿名内部类实现。+ Lambda 表达式。

package com.geek.lambda;

/**
 * @author geek
 */
public class Demo00 {

    public static void main(String[] args) {
        // 传统模式下新线程的创建。
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("threading..." + Thread.currentThread().getName());
            }
        }).start();

        // Lambda。
        new Thread(() -> System.out.println("threading..." + Thread.currentThread().getName())).start();
    }

}



为什么要使用 Lambda 表达式。
  • 它不是解决未知问题的新技术。
  • 对现有解决方案的语义化优化。
  • 需要根据实际需求考虑性能问题。


函数式接口。

  • 函数式接口,就是 Java 类型系统中的接口。
  • 函数式接口,是只包含一个接口方法的特殊接口。
  • 语义化检测注解:@Functionallnterface。
package com.geek;

/**
 * 用户身份认证标记接口。
 *
 * @author geek
 */
@FunctionalInterface
public interface IUserCredential {

    /**
     * 通过用户账号,验证用户身份信息。
     *
     * @param username 要验证的用户账号。
     * @return 身份信息[系统管理员,用户管理员、普通用户。]
     */
    String verifyUser(String username);

//    boolean test();
    // Multiple non-overriding abstract methods found in interface com.geek.IUserCredential

    static String getCredential(String username) {
        if ("admin".equals(username)) {
            return "admin ~ 系统管理员";
        } else if ("manager".equals(username)) {
            return "manager ~ 用户管理员";
        } else {
            return "commons ~ 普通会员用户";
        }
    }

}

package com.geek;

/**
 * 消息传输格式化接口。
 *
 * @author geek
 */
@FunctionalInterface
public interface IMessageFormat {

    /**
     * 消息合法性验证。
     *
     * @param msg 要验证的消息。
     * @return 结果。
     */
    static boolean verifyMessage(String msg) {
        return msg != null;
    }

    /**
     * 消息转换方法。
     *
     * @param message 要转换的消息。
     * @param format  转换的格式[xml/json...]
     * @return 返回转换后的数据。
     */
    String format(String message, String format);

    // 自己定义的方法。
//    void test();
    // Multiple non-overriding abstract methods found in interface com.geek.IMessageFormat

    // 如果是 Object 的方法,编译通过。
    String toString();

}



默认接口方法。
package com.geek;

/**
 * 用户身份认证标记接口。
 *
 * @author geek
 */
@FunctionalInterface
public interface IUserCredential {

    /**
     * 通过用户账号,验证用户身份信息。
     *
     * @param username 要验证的用户账号。
     * @return 身份信息[系统管理员,用户管理员、普通用户。]
     */
    String verifyUser(String username);

//    boolean test();
    // Multiple non-overriding abstract methods found in interface com.geek.IUserCredential

    static String getCredential(String username) {
        if ("admin".equals(username)) {
            return "admin ~ 系统管理员";
        } else if ("manager".equals(username)) {
            return "manager ~ 用户管理员";
        } else {
            return "commons ~ 普通会员用户";
        }
    }

}

package com.geek;

import com.geek.impl.MessageFormatImpl;
import com.geek.impl.UserCredentialImpl;

/**
 * Hello World!
 *
 * @author geek
 */
public class App1 {

    public static void main(String[] args) {
        //        System.out.println( "Hello World!" );
        IUserCredential userCredential = new UserCredentialImpl();
        System.out.println(userCredential.verifyUser("admin"));
        // 系统管理员

        /**
         * 需求改动:
         *      所有的用户验证。可以同时获取用户的验证信息[是否验证成功 | 成功 ~ 返回用户 | null]
         *
         * jdk 1.8 以前只能修改实现类。
         */
        System.out.println(IUserCredential.getCredential("admin"));
        // admin ~ 系统管理员
    }

}



静态接口方法。
package com.geek;

/**
 * 消息传输格式化接口。
 *
 * @author geek
 */
@FunctionalInterface
public interface IMessageFormat {

    /**
     * 消息合法性验证。
     *
     * @param msg 要验证的消息。
     * @return 结果。
     */
    static boolean verifyMessage(String msg) {
        return msg != null;
    }

    /**
     * 消息转换方法。
     *
     * @param message 要转换的消息。
     * @param format  转换的格式[xml/json...]
     * @return 返回转换后的数据。
     */
    String format(String message, String format);

    // 自己定义的方法。
//    void test();
    // Multiple non-overriding abstract methods found in interface com.geek.IMessageFormat

    // 如果是 Object 的方法,编译通过。
    String toString();

}

  • 实现类。
package com.geek.impl;

import com.geek.IMessageFormat;

/**
 * @author geek
 */
public class MessageFormatImpl implements IMessageFormat {

    @Override
    public String format(String message, String format) {
        System.out.println("消息转换。");
        return message;
    }

}

package com.geek;

import com.geek.impl.MessageFormatImpl;
import com.geek.impl.UserCredentialImpl;

/**
 * Hello World!
 *
 * @author geek
 */
public class App1 {

    public static void main(String[] args) {

        String msg = "hello world";
        if (IMessageFormat.verifyMessage(msg)) {
            IMessageFormat format = new MessageFormatImpl();
            System.out.println(format.format(msg, "json"));
        }
    }

}



继承自 Object 的方法。
package com.geek;

/**
 * 消息传输格式化接口。
 *
 * @author geek
 */
@FunctionalInterface
public interface IMessageFormat {

    /**
     * 消息合法性验证。
     *
     * @param msg 要验证的消息。
     * @return 结果。
     */
    static boolean verifyMessage(String msg) {
        return msg != null;
    }

    /**
     * 消息转换方法。
     *
     * @param message 要转换的消息。
     * @param format  转换的格式[xml/json...]
     * @return 返回转换后的数据。
     */
    String format(String message, String format);

    // 自己定义的方法。
//    void test();
    // Multiple non-overriding abstract methods found in interface com.geek.IMessageFormat

    // 如果是 Object 的方法,编译通过。
    @Override
    String toString();

}



Lambda 表达式和函数式接口的关系。

  • 函数式接口,只包含一个操作方法。

  • Lambda 表达式,只能操作一个方法。

  • Java 中的 Lambda 表达式,核心就是一个函数式接口的实现。



匿名内部类。
package com.geek;

import com.geek.impl.MessageFormatImpl;
import com.geek.impl.UserCredentialImpl;

/**
 * Hello World!
 *
 * @author geek
 */
public class App1 {

    public static void main(String[] args) {

        // 匿名内部类实现接口的抽象方法。
        IUserCredential ic2 = new IUserCredential() {
            @Override
            public String verifyUser(String username) {
                return "admin".equals(username) ? "管理员" : "会员";
            }
        };

        System.out.println(ic2.verifyUser("manager"));
        System.out.println(ic2.verifyUser("admin"));

    }

}

package com.geek;

import com.geek.impl.MessageFormatImpl;
import com.geek.impl.UserCredentialImpl;

/**
 * Hello World!
 *
 * @author geek
 */
public class App1 {

    public static void main(String[] args) {

        // Lambda 表达式。针对函数式接口的简单实现。
        IUserCredential ic3 = (String username) -> "admin".equals(username) ? "lbd 管理员" : "lbd 会员";

        System.out.println(ic3.verifyUser("manager"));
        System.out.println(ic3.verifyUser("admin"));
    }

}



jdk 中常见的函数式接口。

java 类型系统内建函数式接口。
  • java.lang.Runnable。
  • java.lang.Comparable。
  • java.lang.Comparator。
  • java.io.FileFilter。

jdk 8 提供了 java.util.function 包,提供了常用的函数式功能接口。

@FunctionalInterface
public interface Predicate<T> {
	// 接受参数对象 T,返回一个 boolean 类型结果。
/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */
package java.util.function;

import java.util.Objects;

/**
 * Represents a predicate (boolean-valued function) of one argument.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #test(Object)}.
 *
 * @param <T> the type of the input to the predicate
 *
 * @since 1.8
 */
@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);

    /**
     * Returns a composed predicate that represents a short-circuiting logical
     * AND of this predicate and another.  When evaluating the composed
     * predicate, if this predicate is {@code false}, then the {@code other}
     * predicate is not evaluated.
     *
     * <p>Any exceptions thrown during evaluation of either predicate are relayed
     * to the caller; if evaluation of this predicate throws an exception, the
     * {@code other} predicate will not be evaluated.
     *
     * @param other a predicate that will be logically-ANDed with this
     *              predicate
     * @return a composed predicate that represents the short-circuiting logical
     * AND of this predicate and the {@code other} predicate
     * @throws NullPointerException if other is null
     */
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    /**
     * Returns a predicate that represents the logical negation of this
     * predicate.
     *
     * @return a predicate that represents the logical negation of this
     * predicate
     */
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    /**
     * Returns a composed predicate that represents a short-circuiting logical
     * OR of this predicate and another.  When evaluating the composed
     * predicate, if this predicate is {@code true}, then the {@code other}
     * predicate is not evaluated.
     *
     * <p>Any exceptions thrown during evaluation of either predicate are relayed
     * to the caller; if evaluation of this predicate throws an exception, the
     * {@code other} predicate will not be evaluated.
     *
     * @param other a predicate that will be logically-ORed with this
     *              predicate
     * @return a composed predicate that represents the short-circuiting logical
     * OR of this predicate and the {@code other} predicate
     * @throws NullPointerException if other is null
     */
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    /**
     * Returns a predicate that tests if two arguments are equal according
     * to {@link Objects#equals(Object, Object)}.
     *
     * @param <T> the type of arguments to the predicate
     * @param targetRef the object reference with which to compare for equality,
     *               which may be {@code null}
     * @return a predicate that tests if two arguments are equal according
     * to {@link Objects#equals(Object, Object)}
     */
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

package com.geek;

import java.util.UUID;
import java.util.function.*;

/**
 * @author geek
 */
public class App2 {

    public static void main(String[] args) {

        Predicate<String> predicate = (String username) -> "admin".equals(username);
//        Predicate<String> predicate = "admin"::equals;
        // 接受参数对象 T,返回一个 boolean 类型结果。
        System.out.println(predicate.test("manager"));
        System.out.println(predicate.test("admin"));
    }

}

@FunctionalInterface
public interface Consumer<T> {
	// 接受参数对象 T,不反回结果。
/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */
package java.util.function;

import java.util.Objects;

/**
 * Represents an operation that accepts a single input argument and returns no
 * result. Unlike most other functional interfaces, {@code Consumer} is expected
 * to operate via side-effects.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #accept(Object)}.
 *
 * @param <T> the type of the input to the operation
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);

    /**
     * Returns a composed {@code Consumer} that performs, in sequence, this
     * operation followed by the {@code after} operation. If performing either
     * operation throws an exception, it is relayed to the caller of the
     * composed operation.  If performing this operation throws an exception,
     * the {@code after} operation will not be performed.
     *
     * @param after the operation to perform after this operation
     * @return a composed {@code Consumer} that performs in sequence this
     * operation followed by the {@code after} operation
     * @throws NullPointerException if {@code after} is null
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

package com.geek;

import java.util.UUID;
import java.util.function.*;

/**
 * @author geek
 */
public class App2 {

    public static void main(String[] args) {

        Consumer<String> consumer = (String msg) -> {
            System.out.println("要发送的消息:" + msg);
            System.out.println("消息发送完成。");
        };
        // 接受参数对象 T,不反回结果。
        consumer.accept("Hello");
        consumer.accept("Hello1");

}

@FunctionalInterface
public interface Function<T, R> {
	// 接受参数对象 T,返回结果对象 R。
/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */
package java.util.function;

import java.util.Objects;

/**
 * Represents a function that accepts one argument and produces a result.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #apply(Object)}.
 *
 * @param <T> the type of the input to the function
 * @param <R> the type of the result of the function
 *
 * @since 1.8
 */
@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);

    /**
     * Returns a composed function that first applies the {@code before}
     * function to its input, and then applies this function to the result.
     * If evaluation of either function throws an exception, it is relayed to
     * the caller of the composed function.
     *
     * @param <V> the type of input to the {@code before} function, and to the
     *           composed function
     * @param before the function to apply before this function is applied
     * @return a composed function that first applies the {@code before}
     * function and then applies this function
     * @throws NullPointerException if before is null
     *
     * @see #andThen(Function)
     */
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    /**
     * Returns a composed function that first applies this function to
     * its input, and then applies the {@code after} function to the result.
     * If evaluation of either function throws an exception, it is relayed to
     * the caller of the composed function.
     *
     * @param <V> the type of output of the {@code after} function, and of the
     *           composed function
     * @param after the function to apply after this function is applied
     * @return a composed function that first applies this function and then
     * applies the {@code after} function
     * @throws NullPointerException if after is null
     *
     * @see #compose(Function)
     */
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    /**
     * Returns a function that always returns its input argument.
     *
     * @param <T> the type of the input and output objects to the function
     * @return a function that always returns its input argument
     */
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

package com.geek;

import java.util.UUID;
import java.util.function.*;

/**
 * @author geek
 */
public class App2 {

    public static void main(String[] args) {

        Function<String, Integer> fun = (String gender) -> "male".equals(gender) ? 1 : 0;
        // 接受参数对象 T,返回结果对象 R。
        System.out.println(fun.apply("male"));
        System.out.println(fun.apply("female"));
    }

}

@FunctionalInterface
public interface Supplier<T> {
	// // 不接受参数,提供 T 对象的创建工厂。
/*
 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */
package java.util.function;

/**
 * Represents a supplier of results.
 *
 * <p>There is no requirement that a new or distinct result be returned each
 * time the supplier is invoked.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #get()}.
 *
 * @param <T> the type of results supplied by this supplier
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Supplier<T> {

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

package com.geek;

import java.util.UUID;
import java.util.function.*;

/**
 * @author geek
 */
public class App2 {

    public static void main(String[] args) {

        Supplier<String> supplier = () -> UUID.randomUUID().toString();
        // 不接受参数,提供 T 对象的创建工厂。
        System.out.println(supplier.get());
        System.out.println(supplier.get());
        System.out.println(supplier.get());
    }

}

@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
	// 接受参数对象 T,返回结果对象。
/*
 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */
package java.util.function;

/**
 * Represents an operation on a single operand that produces a result of the
 * same type as its operand.  This is a specialization of {@code Function} for
 * the case where the operand and result are of the same type.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #apply(Object)}.
 *
 * @param <T> the type of the operand and result of the operator
 *
 * @see Function
 * @since 1.8
 */
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {

    /**
     * Returns a unary operator that always returns its input argument.
     *
     * @param <T> the type of the input and output of the operator
     * @return a unary operator that always returns its input argument
     */
    static <T> UnaryOperator<T> identity() {
        return t -> t;
    }
}

package com.geek;

import java.util.UUID;
import java.util.function.*;

/**
 * @author geek
 */
public class App2 {

    public static void main(String[] args) {

        UnaryOperator<String> unaryOperator = (String img) -> {
            img += "[100x200]";
            return img;
        };
        // 接受参数对象 T,返回结果对象。
        System.out.println(unaryOperator.apply("原图---"));
        // 原图---[100x200]
    }

}

@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> {
	// 接受两个 T 对象,返回一个 T 对象结果。
/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */
package java.util.function;

import java.util.Objects;
import java.util.Comparator;

/**
 * Represents an operation upon two operands of the same type, producing a result
 * of the same type as the operands.  This is a specialization of
 * {@link BiFunction} for the case where the operands and the result are all of
 * the same type.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #apply(Object, Object)}.
 *
 * @param <T> the type of the operands and result of the operator
 *
 * @see BiFunction
 * @see UnaryOperator
 * @since 1.8
 */
@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> {
    /**
     * Returns a {@link BinaryOperator} which returns the lesser of two elements
     * according to the specified {@code Comparator}.
     *
     * @param <T> the type of the input arguments of the comparator
     * @param comparator a {@code Comparator} for comparing the two values
     * @return a {@code BinaryOperator} which returns the lesser of its operands,
     *         according to the supplied {@code Comparator}
     * @throws NullPointerException if the argument is null
     */
    public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) {
        Objects.requireNonNull(comparator);
        return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;
    }

    /**
     * Returns a {@link BinaryOperator} which returns the greater of two elements
     * according to the specified {@code Comparator}.
     *
     * @param <T> the type of the input arguments of the comparator
     * @param comparator a {@code Comparator} for comparing the two values
     * @return a {@code BinaryOperator} which returns the greater of its operands,
     *         according to the supplied {@code Comparator}
     * @throws NullPointerException if the argument is null
     */
    public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) {
        Objects.requireNonNull(comparator);
        return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
    }
}

package com.geek;

import java.util.UUID;
import java.util.function.*;

/**
 * @author geek
 */
public class App2 {

    public static void main(String[] args) {

        BinaryOperator<Integer> binaryOperator = (Integer i1, Integer i2) -> i1 > i2 ? i1 : i2;
        // 接受两个 T 对象,返回一个 T 对象结果。
        System.out.println(binaryOperator.apply(12, 13));
    }

}



Lambda 表达式语法。

必须和接口绑定。

Lambda 表达式基本语法。
package com.geek;

/**
 * @author geek
 */
public class LambdaApp {

    /*
        基本语法。

        - 声明:Lambda 表达式绑定的接口类型。
        - 参数:包含在一对圆括号中,和绑定的接口中的抽象方法的参数个数及顺序一致。
        - 操作符:->
        - 执行代码块:包含在一堆大括号中,出现在操作符号的右侧。

        [接口声明] = (参数) -> {执行代码块};
     */

    public static void main(String[] args) {
        Ilambda1 i1 = () -> {
            System.out.println("hello");
            System.out.println("hello1");
        };
        i1.test();

        Ilambda1 i12 = () -> System.out.println("hello");
        i12.test();

        Ilambda2 i2 = (String s, int a) -> System.out.println(s + " says: my age is " + a);
        i2.test("geek", 3);
    }

    // 没有参数没有返回值的 Lambda 表达式绑定的接口。
    interface Ilambda1 {
        void test();
    }

}



带参数的 Lambda 表达式。
package com.geek;

/**
 * @author geek
 */
public class LambdaApp {

    /*
        基本语法。

        - 声明:Lambda 表达式绑定的接口类型。
        - 参数:包含在一对圆括号中,和绑定的接口中的抽象方法的参数个数及顺序一致。
        - 操作符:->
        - 执行代码块:包含在一堆大括号中,出现在操作符号的右侧。

        [接口声明] = (参数) -> {执行代码块};
     */

    public static void main(String[] args) {

        Ilambda2 i2 = (String s, int a) -> System.out.println(s + " says: my age is " + a);
        i2.test("geek", 3);

        // 可以不写参数类型。
        Ilambda2 i21 = (s, a) -> System.out.println(s + " says: my age is " + a);
        i21.test("geek", 3);
    }

    // 有参数没有返回值的 Lambda 表达式绑定的接口。
    interface Ilambda2 {
        void test(String name, int age);
    }

}



带返回值的 Lambda 表达式。
package com.geek;

/**
 * @author geek
 */
public class LambdaApp {

    /*
        基本语法。

        - 声明:Lambda 表达式绑定的接口类型。
        - 参数:包含在一对圆括号中,和绑定的接口中的抽象方法的参数个数及顺序一致。
        - 操作符:->
        - 执行代码块:包含在一堆大括号中,出现在操作符号的右侧。

        [接口声明] = (参数) -> {执行代码块};
     */

    public static void main(String[] args) {

        Ilambda3 i3 = (x, y) -> x + y;
        System.out.println(i3.test(1, 2));
    }
    
    // 有参数和返回值的 Lambda 表达式绑定的接口。
    interface Ilambda3 {
        int test(int x, int y);
    }

}



变量捕获。

匿名内部类中的变量捕获。
package com.geek;

/**
 * @author geek
 */
public class App3 {

    private String s1 = "全局变量";

    public static void main(String[] args) {
        App3 app3 = new App3();
        app3.testInnerClass();
    }

    // 匿名内部类中对变量的访问。
    private void testInnerClass() {
        String s2 = "局部变量";

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

            @Override
            public void run() {
                // 访问全局变量。
//                System.out.println(this.s1);// this 关键字 ~ 表示当前内部类型的对象。
                System.out.println(s1);

                // 访问局部变量。
                System.out.println(s2);
//                s2 = "hello";// 不能对局部变量进行修改(final)。

                System.out.println(s3);
                System.out.println(this.s3);
            }
        }).run();
    }

}



Lambda 表达式中的变量捕获。
package com.geek;

/**
 * @author geek
 */
public class App3 {

    private String s1 = "全局变量";

    public static void main(String[] args) {
        App3 app3 = new App3();
//        app3.testInnerClass();
        app3.testLambda();
    }

    // Lambda 表达式变量捕获。
    private void testLambda() {
        String s2 = "局部变量 Lambda";

        new Thread(() -> {
            String s3 = "内部变量 Lambda";

            // 访问全局变量。
            System.out.println(this.s1);// this 关键字 ~ 表示的就是所属方法所在的类型的对象。
            // 访问局部变量。
            System.out.println(s2);
//                s2 = "hello";// 不能对局部变量进行修改(final)。

            System.out.println(s3);
            s3 = "Lambda 内部变量直接修改。";
        }).start();
    }

}



Lambda 表达式类型检查。

Lambda 表达式类型检查。
package com.geek;

import java.util.ArrayList;
import java.util.List;

@FunctionalInterface
interface MyInterface<T, R> {

    R strategy(T t, R r);

}

/**
 * @author geek
 */
public class App4 {

    private static void test(MyInterface<String, List> inter) {
        List<String> list = inter.strategy("hello", new ArrayList());
        System.out.println(list);
    }

    public static void main(String[] args) {
        test(new MyInterface<String, List>() {
            @Override
            public List strategy(String s, List list) {
                list.add(s);
                return list;
            }
        });

        test((x, y) -> {
            y.add(x);
            return y;
        });

        /*
        (x, y) -> { ... } ==> test(param) ==> param == MyInterface ==> Lambda 表达式 ==> MyInterface 类型。
        这个就是对于 Lambda 表达式的类型检查。MyInterface 接口就是 Lambda 表达式的目标类型(Target Typing)。
         */
    }

}



Lambda 参数类型检查。
package com.geek;

import java.util.ArrayList;
import java.util.List;

@FunctionalInterface
interface MyInterface<T, R> {

    R strategy(T t, R r);

}

/**
 * @author geek
 */
public class App4 {

    private static void test(MyInterface<String, List> inter) {
        List<String> list = inter.strategy("hello", new ArrayList());
        System.out.println(list);
    }

    public static void main(String[] args) {
        test(new MyInterface<String, List>() {
            @Override
            public List strategy(String s, List list) {
                list.add(s);
                return list;
            }
        });

        test((x, y) -> {
            y.add(x);
            return y;
        });

        /*
        (x, y) -> { ... } ==> test(param) ==> param == MyInterface ==> Lambda 表达式 ==> MyInterface 类型。
        这个就是对于 Lambda 表达式的类型检查。MyInterface 接口就是 Lambda 表达式的目标类型(Target Typing)。

        (x, y) -> { ... } ==> MyInterface.strategy(T t, R r) ==> MyInterface<String, List> inter
            ==> T==String R==List ==> lambda (x, y) == strategy(T t, R r) ==> x == T == String, y == R == List
            Lambda 表达式参数的类型检查。
         */

        test((x, y) -> {
            y.add(x);
            return y;

//            x.add();// Cannot resolve method 'add()'
        });
    }

}



方法重载和 Lambda 表达式。

Java 类型系统中的方法重载。
方法重载的实现。
当方法重载遇上 Lambda 表达式。
package com.geek;

/**
 * @author geek
 */
public class App5 {

    public static void main(String[] args) {
        App5 app = new App5();
        app.lambdaMethod(new Param1() {
            @Override
            public void outInfo(String info) {
                System.out.println(info);
            }
        });

        app.lambdaMethod(new Param2() {
            @Override
            public void outInfo(String info) {
                System.out.println(info);
            }
        });

        /*
        Lambda 表达式存在类型检查 ->自动推到 Lambda 表达式的目标类型。
        lambdaMethod(); 方法是重载方法。
            => Param1 函数式接口。
            => Param2 函数式接口。
            调用方法 => 传递 Lambda 表达式 => 自动推导
                => Param1 | Param2
         */
        // Ambiguous method call.
        // Both lambdaMethod (Param1) in App5
        // and lambdaMethod (Param2) in App5 match
//        app.lambdaMethod((String info) -> {
//            System.out.println(info);
//        });
    }

    // 重载方法。
    public void lambdaMethod(Param1 param) {
        param.outInfo("hello, param1.");
    }

    public void lambdaMethod(Param2 param) {
        param.outInfo("hello, param2.");
    }

    interface Param1 {
        void outInfo(String info);
    }

    interface Param2 {
        void outInfo(String info);
    }

}



深入理解 Lambda 表达式。

  • Lambda 表达式底层解析运行原理。
  • Lambda 表达式在 JVM 底层解析成私有静态方法和匿名内部类型。
  • 通过实现接口的匿名内部类型中接口方法调用静态实现方法,完成 Lambda 表达式的执行。
geek@ubuntu:~/IdeaProjects/lambda_geek/src/main/java/com/geek$ javac App.java 
geek@ubuntu:~/IdeaProjects/lambda_geek/src/main/java/com/geek$ javap -p App.class
Compiled from "App.java"
public class com.geek.App {
  public com.geek.App();
  public static void main(java.lang.String[]);
  private static void lambda$main$0(java.lang.String);
}

C:\Users\geek\Desktop>G:\lyfGeek\ProgramFiles\Java\jdk1.8.0_241\bin\javac App.java

C:\Users\geek\Desktop>G:\lyfGeek\ProgramFiles\Java\jdk1.8.0_241\bin\javap -p App.class
Compiled from "App.java"
public class App {
  public App();
  public static void main(java.lang.String[]);
  private static void lambda$main$0(java.lang.String);
}
C:\Users\geek\Desktop>G:\lyfGeek\ProgramFiles\Java\jdk1.8.0_241\bin\java -Djdk.internal.lambda.dumpProxyClasses App
lambda!

C:\Users\geek\Desktop>G:\lyfGeek\ProgramFiles\Java\jdk1.8.0_241\bin\javap -p App$$Lambda$1.class
final class App$$Lambda$1 implements IMarkUp {
  private App$$Lambda$1();
  public void markUp(java.lang.String);
}


方法引用。

静态方法引用。


实例方法引用。


构造方法引用。
package com.geek;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

interface IPerson {

    /**
     * 抽象方法。通过制定类型的构造方法初始化对象数据。
     *
     * @param name
     * @param gender
     * @param age
     * @return
     */
    Person initPerson(String name, String gender, int age);

}

/**
 * @author geek
 */
public class Test {

    public static void main(String[] args) {

        // 静态方法引用。
        // 类型名称.方法名称(); ==> 类型名称::方法名称。
        List<Person> personList = new ArrayList<>();
        personList.add(new Person("Geek1", "男", 25));
        personList.add(new Person("Geek2", "男", 18));
        personList.add(new Person("Geek3", "男", 3));
        personList.add(new Person("Geek4", "男", 21));
        personList.add(new Person("Geek5", "男", 9));

        // 排序。匿名内部类。
        Collections.sort(personList, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
//                return 0;
                return o1.getAge() - o2.getAge();
            }
        });
        System.out.println(personList);

        // 排序。Lambda。
        Collections.sort(personList, (p1, p2) -> p1.getAge() - p2.getAge());
        System.out.println(personList);

        // 排序。静态方法引用。
        Collections.sort(personList, Person::compareByAge);

        System.out.println(personList);

        // ~ ~

        // 排序。实例方法引用。
        // 创建类型对应的一个对象。 ==> 对象::实例方法名称。
        PersonUtil personUtil = new PersonUtil();
        Collections.sort(personList, personUtil::compareByName);
        System.out.println("Geek1".hashCode());
        System.out.println("Geek2".hashCode());
        System.out.println(personList);
        // 68679309(Geek1)
        //68679310(Geek2)
        //[Person(name=Geek1, gender=男, age=25), Person(name=Geek2, gender=男, age=18), Person(name=Geek3, gender=男, age=3), Person(name=Geek4, gender=男, age=21), Person(name=Geek5, gender=男, age=9)]

        // 构造方法引用。绑定函数式接口。
        IPerson iPerson = Person::new;
        Person person = iPerson.initPerson("Tom", "男", 23);
        System.out.println(person);
    }

}

@Data
@AllArgsConstructor
@NoArgsConstructor
class Person {

    private String name;
    private String gender;
    private int age;

    static int compareByAge(Person p1, Person p2) {
        return p1.getAge() - p2.getAge();
    }

}

class PersonUtil {

    // 增加一个实例方法。
    int compareByName(Person p1, Person p2) {
        return p1.getName().hashCode() - p2.getName().hashCode();
    }

}



Stream。

package com.geek;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author geek
 */
public class StreamTest {

    public static void main(String[] args) {

        // 测试数据:存储多个账号的列表。
        List<String> accounts = new ArrayList<>();
        accounts.add("tom");
        accounts.add("jerry");
        accounts.add("beita");
        accounts.add("shuke");
        accounts.add("geek");

        // 长度 >= 5 的有效账号。
        for (String account : accounts) {
            if (account.length() >= 5) {
                System.out.println("有效账号:" + account);
            }
        }

        // 迭代方式。
        Iterator<String> iterator = accounts.iterator();
        while (iterator.hasNext()) {
            String account = iterator.next();
            if (account.length() >= 5) {
                System.out.println("it 有效账号:" + account);
            }
        }

        // Stream 结合 Lambda 表达式。
        List validAccounts = accounts.stream().filter(s -> s.length() >= 5).collect(Collectors.toList());
        Stream<String> stream = accounts.stream();
        System.out.println(stream);// java.util.stream.ReferencePipeline$Head@2d98a335
        System.out.println(validAccounts);
    }

}



Stream 集合操作。

package com.geek;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * - 集合操作。
 * - Stream 处理流程。
 *  数据源。
 *  数据转换。
 *  获取结果。
 * - 获取 Stream 对象。
 *  - 从集合或数组中获取。
 *   Collection.stream();。
 *   Collection.parallelStream();。
 *   Arrays.stream(T t);。
 *  - BufferReader。
 *   BufferReader.lines();。
 *  - 静态工厂。
 *   java.util.stream.IntStream.range();。
 *   java.nio.file.Files.walk();。
 *  - 自定构建。
 *   java.util.Spliterator();。
 *  - more。
 *   Random.ints();。
 *   Pattern.splitAsStream();。
 * <p>
 * - 中间操作 API。(intermediate)。
 * 操作结果是一个 Stream。中间操作可以有一或多个连续的中间操作,需要注意的是,中间操作只记录操作方式,不做具体执行,知道结束操作发生时,才做数据的最终执行。
 * 中间操作就是业务逻辑处理。
 * 中间操作过程:
 *  无状态:数据处理时,不受前置操作的影响。
 * map / filter / peek / parallel / sequential / unordered。
 *  有状态:数据处理时,受到前置操作的影响。
 * distinct / sorted / limit / skip。
 * <p>
 * - 终结操作 / 结束操作。(terminal)。
 * 一个 Stream 对象,只能有一个 Terminal 操作。这个操作一旦发生,就会真实处理数据,生成对应的处理结果。
 * 终结操作。
 * —— 短路操作:当前的 Stream 对象必须处理完集合中所有数据,才能得到处理结果。
 * forEach / forEachOrdered / toArray / reduce / collect / min / max / count / iterator。
 * —— 非短路操作:当前的 Stream 对象在处理过程中,一旦满足某个条件,就可以得到结果。
 * anyMatch / allMatch / noneMatch / findFirst / findAny。
 * short-circuiting。无限大的 Stream -> 有限大的 Stream。
 *
 * @author geek
 */
public class ArraysDemo {

    public static void main(String[] args) {
        // 批量数据 --> Stream 对象。
        // 多个数据。
        Stream<String> stream1 = Stream.of("admin", "Tom", "Jerry");
        System.out.println("stream1 = " + stream1);

        // 数组。
        String[] strings = {"geek", "haha"};
        Stream<String> stream2 = Arrays.stream(strings);
        System.out.println("stream2 = " + stream2);

        // 列表。
        List<String> list = new ArrayList<>();
        list.add("少林");
        list.add("武当");
        list.add("青城");
        list.add("峨眉");
        list.add("崆峒");
        Stream<String> stream3 = list.stream();
        System.out.println("stream3 = " + stream3);

        // 集合。
        Set<String> set = new HashSet<>();
        set.add("少林罗汉拳");
        set.add("武当长拳");
        set.add("青城剑法");
        Stream<String> stream4 = set.stream();
        System.out.println("stream4 = " + stream4);

        // map。
        Map<String, Integer> map = new HashMap<>();
        map.put("geek", 3);
        map.put("Tom", 12);
        map.put("Jerry", 11);
        Stream<Map.Entry<String, Integer>> stream5 = map.entrySet().stream();
        System.out.println("stream5 = " + stream5);

        // Stream 对象对于基本数据类型的功能封装。
        // int / long / long。
        IntStream.of(10, 20, 30).forEach(System.out::println);
        IntStream.range(1, 5).forEach(System.out::println);// 1 ~ 4。
        IntStream.rangeClosed(1, 5).forEach(System.out::println);// 1 ~ 5。

        // Stream 对象 --> 转换得到指定的数据类型。
        // 数组。
//        String[] strings1 = stream1.toArray(String[]::new);
//        System.out.println("strings1 = " + strings1);

        // 字符串。
//        String string = stream1.collect(Collectors.joining()).toString();
//        System.out.println("string = " + string);
        // Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
        // string = adminTomJerry

        // 列表。
//        List<String> list1 = stream1.collect(Collectors.toList());
//        System.out.println("list1 = " + list1);
        // list1 = [admin, Tom, Jerry]

        // 集合。
//        Set<String> set1 = stream1.collect(Collectors.toSet());
//        System.out.println("set1 = " + set1);
        // set1 = [Tom, admin, Jerry]

        // map。
        Map<String, String> map1 = stream1.collect(Collectors.toMap(x -> x, y -> "value:" + y));
        System.out.println("map1 = " + map1);
        // map1 = {Tom=value:Tom, admin=value:admin, Jerry=value:Jerry}
    }

}



Stream API。

Stream 操作原理。

操作集合元素。

package com.geek;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * @author geek
 */
public class APIDemo {

    public static void main(String[] args) {
        List<String> accountList = new ArrayList<>();
        accountList.add("Geek");
        accountList.add("Tom");
        accountList.add("Jerry");
        accountList.add("luzhishen");
        accountList.add("wusong");

        // map(); 中间操作。map(); 方法接收一个 Functional 接口。
//        accountList = accountList.stream().map(x -> "梁山好汉:" + x).collect(Collectors.toList());
//        accountList.forEach(System.out::println);
        System.out.println("~ ~ ~ ~ ~ ~ ~");

        // filter(); 添加过滤条件,拂绿符合条件的用户。
//        accountList = accountList.stream().filter(x -> x.length() > 5).collect(Collectors.toList());
//        accountList.forEach(System.out::println);

        // forEach(); 增强型循环。
//        accountList.forEach(x -> System.out.println("forEach => " + x));
        // 如果要多次迭代操作。
//        accountList.forEach(x -> System.out.println("forEach => " + x));
//        accountList.forEach(x -> System.out.println("forEach => " + x));
        // 冗余。
        // ↓ ↓ ↓

        // peek(); 中间操作。迭代数据完成数据的依次处理过程。
//        accountList.stream()
//                .peek(x -> System.out.println("peek 1" + x))
//                .peek(x -> System.out.println("peek 2" + x))
//                .forEach(System.out::println);
//
        // Stream 中对于数字运算的支持。
        List<Integer> list = new ArrayList<>();
        list.add(20);
        list.add(17);
        list.add(3);
        list.add(11);
        list.add(26);
        list.add(27);
        list.add(27);

        // skip(); 中间操作,有状态,跳过部分数据。
//        list.stream().skip(3).forEach(System.out::println);

        // limit(); 中间操作,有状态,限制输出数据量。
//        list.stream().skip(3).limit(2).forEach(System.out::println);

        // distinct(); 中间操作,有状态,剔除重复数据。
//        list.stream().distinct().forEach(System.out::println);

        // sorted(); 中间操作,有状态,排序。
        // max(); 获取最大值。
        Optional<Integer> optional = list.stream().max((x, y) -> x - y);
        System.out.println(optional.get());
        // min(); 获取最小值。

        // reduce(); 合并处理数据。
        Optional<Integer> optional1 = list.stream().reduce((sum, x) -> sum + x);
        System.out.println(optional1.get());
    }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lyfGeek

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值