本文最后更新于 2024-04-01,欢迎来到我的Blog! https://www.zpeng.site/

Java8新特性Lambda表达式

1.介绍

Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包,和传统数学上的意义有区别。

  • Java8引入了一个新的操作符: ->,该操作符称为箭头操作符或Lambda操作符,箭头操作符将Lambda表达式拆分为2部分

  • 左侧:Lambda表达式的参数列表

  • 右侧:Lambda表达式中所执行的功能,即Lambda体

2.语法格式

左侧:表达式的参数列表(接口中方法的参数列表)

右侧:接口中方法的实现

package com.example.useragent.demos.web.Lambda;

import java.util.Comparator;
import java.util.function.Consumer;

public class TestLambda {
    public static void main(String[] args) {
        //语法格式1:无参无返回值
        //() -> System.out.println("Hello Lambda!");
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello World!");
            }
        };
        r1.run();

        Runnable r2 = () -> System.out.println("Hello Lambda!");
        r2.run();

        System.out.println("--------------------------");

        //语法格式2:一个参数无返回值
        //(x) -> System.out.println(x)
        Consumer<String> con = (x) -> System.out.println(x);
        con.accept("Hello Consumer1");
        // 只有一个参数,参数的小括号可以省略
        Consumer<String> consumer = x -> System.out.println(x);
        consumer.accept("Hello Consumer2");

        System.out.println("--------------------------");

        //语法格式3:有两个参数,并且lambda 体中有多条语句,并且有返回值
        Comparator<Integer> com1 = (x, y) -> {
            System.out.println("函数式接口");
            return Integer.compare(x, y);
        };
        System.out.println(com1.compare(2, 4));

        System.out.println("--------------------------");

        //语法格式4:有两个以上参数,有返回值,若 lambda 体中只有一条语句,return和大括号都可以省略不写
        Comparator<Integer> com2 = (Integer x, Integer y) -> Integer.compare(x, y);
        System.out.println(com2.compare(4, 2));
        // 表达式的参数列表的数据类型可以省略不写,因为JVM可以通过上下文推断出数据类型,即“类型推断”
        Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
        System.out.println(com.compare(4, 2));

        System.out.println("--------------------------");
    }
}

3.函数式接口

只包含一个抽象方法的接口,就称为函数式接口。我们可以通过 lambda表达式来创建该接口的实现对象。我们可以在任意函数式接口上使用 @FunctionalInterface 注解,这样做可以用于检测它是否是一个函数式接口,同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。

package com.example.useragent.demos.web.Lambda;

//们可以在任意函数式接口上使用 @FunctionalInterface 注解,这样做可以用于检测它是否是一个函数式接口
@FunctionalInterface
public interface MyFun {
    public Integer getValue(Integer num);
}
package com.example.useragent.demos.web.Lambda;

public class TestLambda {
    public static void main(String[] args) {
       
        Integer num = operation(100, (x) -> x + 88);
        System.out.println(num);

        MyFun myfun = (x) -> x + 88;
        System.out.println(myfun.getValue(100));
    }

    public static Integer operation(Integer num, MyFun mf) {
        return mf.getValue(num);
    }
}

4.内置函数式接口

函数式接口

参数类型

返回类型

用途

Consumer<T>

消费型接口

T

void

对类型为 T 的对象应用操作,包含方法:void accept(T t);

Supplier<T>

供给型接口

T

返回类型为 T 对象,包含方法:T get();

Function<T, R>

函数型接口

T

R

对类型为 T 的对象应用操作,并返回结果,结果是R类型的对象。包含方法:R apply(T t);

Predicate<T>

断言型接口

T

boolean

确定类型为 T 的对象是否满足某约束,并返回 boolean 值。包含方法:boolean test(T t);

  1. Consumer<T>:消费型接口

    void accept(T t);

  2. Supplier<T>:供给型接口

    T get();

  3. Function(T,R):函数型接口

    R apply(T t);

  4. Predicate<T>:断言型接口

    boolean test(T t);

4.1Consumer<T>消费型接口

接口

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);


    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

测试

@Test
void test1() {
    happy(1000,(X)-> System.out.println("消费了1000元!"));
}
public void happy(double money, Consumer con){
    con.accept(money);
}

结果

4.2Supplier<T>供给型接口

接口

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();
}

测试

    /**
     * 产生指定的整数集合放到集合中
     * Iterable接口的forEach方法的定义:方法中使用到了Consumer消费型接口,
     * default void forEach(Consumer<? super T> action) {
     * Objects.requireNonNull(action);
     * for (T t : this) {
     * action.accept(t);
     * }
     * }
     */
    @Test
    public void test2() {
        List list = addNumInList(10, () -> (int) (Math.random() * 100));
        list.forEach(t -> System.out.println(t));
    }

    public List addNumInList(int size, Supplier<Integer> supplier) {
        List<Integer> list = new ArrayList();
        for (int i = 0; i < size; i++) {
            list.add(supplier.get());
        }
        return list;
    }

结果

4.3Function<T, R>函数型接口

接口

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);



    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;
    }
}

测试

/**
 * 使用函数式接口处理字符串。
 */
@Test
public void test3() {
    System.out.println(handleStr("abc", (String s) -> s.toUpperCase()));
}
public String handleStr(String s, Function<String, String> f) {
    return f.apply(s);
}

结果

4.4Predicate<T>断言型接口

接口

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);


    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);
    }


    @SuppressWarnings("unchecked")
    static <T> Predicate<T> not(Predicate<? super T> target) {
        Objects.requireNonNull(target);
        return (Predicate<T>)target.negate();
    }
}

测试

/**
 * 自定义条件过滤字符串集合
 */
@Test
public void test4() {
    List<String> strings = Arrays.asList("啊", "23", "666", "7777","88888");
    List<String> stringList1 = filterStr(strings, (s) -> s.length() > 3);
    for (String s : stringList1) {
        System.out.println(s);
    }
}
public List<String> filterStr(List<String> list, Predicate<String> predicate) {
    ArrayList result = new ArrayList();
    for (int i = 0; i < list.size(); i++) {
        if (predicate.test(list.get(i))) {
            result.add(list.get(i));
        }
    }
    return result;
}

结果

5.例子

//1. 使用Lambda表达式进行集合遍历
//未使用Lambda表达式:
List<String> list = Arrays.asList("apple", "banana", "orange");
for (String fruit : list) {
    System.out.println(fruit);
}
//使用Lambda表达式:
List<String> list = Arrays.asList("apple", "banana", "orange");
list.forEach(fruit -> System.out.println(fruit));

//2. 使用Lambda表达式进行排序
//未使用Lambda表达式:
List<String> list = Arrays.asList("apple", "banana", "orange");
Collections.sort(list, new Comparator<String>() {
    public int compare(String s1, String s2) {
        return s1.compareTo(s2);
    }
});
//使用Lambda表达式:
List<String> list = Arrays.asList("apple", "banana", "orange");
Collections.sort(list, (s1, s2) -> s1.compareTo(s2));

//3. 使用Lambda表达式进行过滤
//未使用Lambda表达式:
List<String> list = Arrays.asList("apple", "banana", "orange");
List<String> filteredList = new ArrayList<String>();
for (String fruit : list) {
    if (fruit.startsWith("a")) {
        filteredList.add(fruit);
    }
}
//使用Lambda表达式:
List<String> list = Arrays.asList("apple", "banana", "orange");
List<String> filteredList = list.stream().filter(fruit -> fruit.startsWith("a")).collect(Collectors.toList());

//4. 使用Lambda表达式进行映射
//未使用Lambda表达式:
List<String> list = Arrays.asList("apple", "banana", "orange");
List<Integer> lengths = new ArrayList<Integer>();
for (String fruit : list) {
    lengths.add(fruit.length());
}
//使用Lambda表达式:
List<String> list = Arrays.asList("apple", "banana", "orange");
List<Integer> lengths = list.stream().map(fruit -> fruit.length()).collect(Collectors.toList());

//5. 使用Lambda表达式进行归约
//未使用Lambda表达式:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
int sum = 0;
for (int i : list) {
    sum += i;
}
//使用Lambda表达式:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
int sum = list.stream().reduce(0, (a, b) -> a + b);

//6. 使用Lambda表达式进行分组
//未使用Lambda表达式:
List<String> list = Arrays.asList("apple", "banana", "orange");
Map<Integer, List<String>> grouped = new HashMap<Integer, List<String>>();
for (String fruit : list) {
    int length = fruit.length();
    if (!grouped.containsKey(length)) {
        grouped.put(length, new ArrayList<String>());
    }
    grouped.get(length).add(fruit);
}
//使用Lambda表达式:
List<String> list = Arrays.asList("apple", "banana", "orange");
Map<Integer, List<String>> grouped = list.stream().collect(Collectors.groupingBy(fruit -> fruit.length()));

//7. 使用Lambda表达式进行函数式接口的实现
//未使用Lambda表达式:
public interface MyInterface {
    public void doSomething(String input);
}
MyInterface myObject = new MyInterface() {
    public void doSomething(String input) {
        System.out.println(input);
    }
};
myObject.doSomething("Hello World");
//使用Lambda表达式:
MyInterface myObject = input -> System.out.println(input);
myObject.doSomething("Hello World");

//8. 使用Lambda表达式进行线程的创建
//未使用Lambda表达式:
Thread thread = new Thread(new Runnable() {
    public void run() {
        System.out.println("Thread is running.");
    }
});
thread.start();
//使用Lambda表达式:
Thread thread = new Thread(() -> System.out.println("Thread is running."));
thread.start();

//9. 使用Lambda表达式进行Optional的操作
//未使用Lambda表达式:
String str = "Hello World";
if (str != null) {
    System.out.println(str.toUpperCase());
}
//使用Lambda表达式:
Optional<String> str = Optional.ofNullable("Hello World");
str.map(String::toUpperCase).ifPresent(System.out::println);

//10. 使用Lambda表达式进行Stream的流水线操作
//未使用Lambda表达式:
List<String> list = Arrays.asList("apple", "banana", "orange");
List<String> filteredList = new ArrayList<String>();
for (String fruit : list) {
    if (fruit.startsWith("a")) {
        filteredList.add(fruit.toUpperCase());
    }
}
Collections.sort(filteredList);
//使用Lambda表达式:
List<String> list = Arrays.asList("apple", "banana", "orange");
List<String> filteredList = list.stream().filter(fruit -> fruit.startsWith("a")).map(String::toUpperCase).sorted()