自学内容网 自学内容网

07 Lambda和StreamAPI

目录

1.Lambda表达式

语法格式:

简单示例

2.函数式接口

常见的函数式接口

1. Supplier

2. Consumer

3. Function,>

4. Predicate

总结

3.流式编程——StreamAPI

基本概念

常见的 Stream 操作

1. 创建 Stream

2. 中间操作

3. 终端操作

简单练习


1.Lambda表达式

java的核心编程思想——面向对象:强调的是对象,有什么属性,什么能力等等。

函数式编程思想——强调结果:不关心过程,对应的代表就是Lambda表达式。

Lambda表达式是一种匿名函数,可以在代码中用于创建简洁的内联函数。它们通常用于需要简单功能的地方,尤其是在使用函数作为参数的情况下,如排序、过滤或映射操作。

语法格式:
(parameters) -> expression

或者是

(parameters) -> { statements; }
简单示例

假设我们有一个列表,想通过lambda表达式来过滤出偶数:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
​
public class LambdaExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
        List<Integer> evenNumbers = numbers.stream()
                                           .filter(x -> x % 2 == 0)
                                           .collect(Collectors.toList());
        System.out.println(evenNumbers);  // 输出 [2, 4, 6]
    }
}

2.函数式接口

Lambda表达式是有适用前提的:

1.必须是函数式接口做方法参数传递 2.函数式接口:有且只有一个抽象方法的接口,用@FunctionalInterface去检测

常见的函数式接口

SupplierConsumerFunctionPredicate 是最常用的几个。这些接口(40多个)位于 java.util.function 包下,主要用于支持Lambda表达式和方法引用,使得代码更简洁、更具有表现力。

1. Supplier<T>

Supplier 接口表示一个无参且有返回值的函数。它的方法 get() 返回一个结果。

接口定义:

@FunctionalInterface
public interface Supplier<T> {
    T get();
}

示例

Supplier<String> supplier = () -> "Hello, World!";
String result = supplier.get();
System.out.println(result);  // 输出 Hello, World!
2. Consumer<T>

Consumer 接口表示一个接受单个输入参数并且没有返回值的函数。它的方法 accept(T t) 处理传入的参数。

接口定义:

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
}

示例:

Consumer<String> consumer = System.out::println;
consumer.accept("Hello, World!");  // 输出 Hello, World!
3. Function<T, R>

Function 接口表示一个接受一个参数并产生一个结果的函数。它的方法 apply(T t) 将输入参数转换为输出结果。

接口定义:

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
}

示例:

Function<String, Integer> function = String::length;
int length = function.apply("Hello, World!");
System.out.println(length);  // 输出 13
4. Predicate<T>

Predicate 接口表示一个接受一个参数并返回一个布尔值的函数。它的方法 test(T t) 检查某个条件是否满足。

接口定义:

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
}

示例:

Predicate<String> predicate = s -> s.length() > 5;
boolean isLong = predicate.test("Hello, World!");
System.out.println(isLong);  // 输出 true
总结
  • Supplier< T >: 无参,有返回值。

  • Consumer<T>: 有参,无返回值。

  • Function<T, R>: 有参,有返回值。

  • Predicate<T>: 有参,返回布尔值。

3.流式编程——StreamAPI

Stream API 提供了一种声明式的方式对数据进行操作,支持函数式编程风格,使代码更加简洁、易读和高效,是一个强大的工具,用于处理集合数据。

基本概念
  1. Stream: 数据的序列,支持连续的、基于某种规则的操作。

  2. Pipeline: 流水线,由源(数据源)、中间操作(Intermediate Operations)和终端操作(Terminal Operations)组成。

  3. 懒求值: 中间操作不会立即执行,而是在终端操作触发时才会执行。

常见的 Stream 操作
1. 创建 Stream
  • 从集合创建:

    List<String> list = Arrays.asList("apple", "banana", "cherry");
    Stream<String> stream = list.stream();
  • 从数组创建:

    String[] array = {"apple", "banana", "cherry"};
    Stream<String> stream = Arrays.stream(array);
  • 从文件创建:

    try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) {
        lines.forEach(System.out::println);
    } catch (IOException e) {
        e.printStackTrace();
    }
2. 中间操作
  • filter: 过滤流中的元素。

    List<String> fruits = Arrays.asList("apple", "banana", "cherry", "date");
    List<String> filteredFruits = fruits.stream()
                                       .filter(fruit -> fruit.startsWith("a"))
                                       .collect(Collectors.toList());
  • map: 转换流中的元素。

    List<String> fruits = Arrays.asList("apple", "banana", "cherry", "date");
    List<Integer> lengths = fruits.stream()
                                 .map(String::length)
                                 .collect(Collectors.toList());
  • flatMap: 将流中的每个元素转换为一个新的流,然后将所有这些流合并成一个流。

    List<List<Integer>> lists = Arrays.asList(
        Arrays.asList(1, 2),
        Arrays.asList(3, 4)
    );
    List<Integer> flatList = lists.stream()
                                  .flatMap(List::stream)
                                  .collect(Collectors.toList());
  • distinct: 去重。

    List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5);
    List<Integer> distinctNumbers = numbers.stream()
                                           .distinct()
                                           .collect(Collectors.toList());
  • sorted: 排序。

    List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5, 9, 2, 6);
    List<Integer> sortedNumbers = numbers.stream()
                                         .sorted()
                                         .collect(Collectors.toList());
3. 终端操作
  • forEach: 遍历流中的每个元素。

    List<String> fruits = Arrays.asList("apple", "banana", "cherry", "date");
    fruits.stream()
          .forEach(System.out::println);
  • collect: 将流中的元素收集到一个集合中。

    List<String> fruits = Arrays.asList("apple", "banana", "cherry", "date");
    List<String> collectedFruits = fruits.stream()
                                         .filter(fruit -> fruit.startsWith("a"))
                                         .collect(Collectors.toList());
  • reduce: 对流中的元素进行累积操作。

    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    int sum = numbers.stream()
                     .reduce(0, Integer::sum);
  • anyMatch: 检查流中是否有任何元素匹配给定的条件。

    List<String> fruits = Arrays.asList("apple", "banana", "cherry", "date");
    boolean hasApple = fruits.stream()
                             .anyMatch(fruit -> fruit.equals("apple"));
  • allMatch: 检查流中的所有元素是否都匹配给定的条件。

    List<String> fruits = Arrays.asList("apple", "banana", "cherry", "date");
    boolean allStartWithA = fruits.stream()
                                  .allMatch(fruit -> fruit.startsWith("a"));
  • noneMatch: 检查流中没有任何元素匹配给定的条件。

    List<String> fruits = Arrays.asList("apple", "banana", "cherry", "date");
    boolean noneStartWithZ = fruits.stream()
                                   .noneMatch(fruit -> fruit.startsWith("z"));
  • findFirst: 返回流中的第一个元素。

    List<String> fruits = Arrays.asList("apple", "banana", "cherry", "date");
    Optional<String> firstFruit = fruits.stream()
                                        .findFirst();
  • count: 计算流中的元素数量。

    List<String> fruits = Arrays.asList("apple", "banana", "cherry", "date");
    long count = fruits.stream()
                       .count();
简单练习

1.数据准备:数组存放人物对象,包含名字和年龄,使用《剑来》里的人物。

2.操作练习:

分别进行如下操作:

  • 获取男性队伍并打印。

  • 获取女性队伍并打印。

  • 男性队伍按年龄倒序排序,取前3。确保结果包含"陈平安"。

  • 女性队伍按年龄倒序排序,去掉前2。确保结果包含"宁姚"。

  • 合并两个队伍,并打印。

Person定义:

public class Person {
    private String name;
    private int age;
    private String gender;
​
    public Person(String name, int age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }
​
    public String getName() {
        return name;
    }
​
    public int getAge() {
        return age;
    }
​
    public String getGender() {
        return gender;
    }
​
    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + ", gender='" + gender + "'}";
    }
}

StreamAPITest:

public class StreamAPITest {
    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
                new Person("陈平安", 20, "男"),
                new Person("宁姚", 18, "女"),
                new Person("崔东山", 22, "男"),
                new Person("李宝瓶", 16, "女"),
                new Person("裴钱", 15, "女"),
                new Person("朱河", 25, "男"),
                new Person("陈灵均", 21, "男"),
                new Person("陈如初", 17, "女"),
                new Person("周米粒", 14, "女"),
                new Person("李二", 33, "男"),
                new Person("郑大风", 35, "男")
        );
​
        // 1. 获取男性队伍并打印
        List<Person> maleTeam = people.stream()
                .filter(person -> person.getGender().equals("男"))
                .collect(Collectors.toList());
        System.out.println("男性队伍:");
        maleTeam.forEach(System.out::println);
​
        // 2. 获取女性队伍并打印
        List<Person> femaleTeam = people.stream()
                .filter(person -> person.getGender().equals("女"))
                .collect(Collectors.toList());
        System.out.println("女性队伍:");
        femaleTeam.forEach(System.out::println);
​
        // 3. 男性队伍按年龄排序,取前三,确保包含陈平安
        List<Person> topThreeMales = maleTeam.stream()
                .sorted(Comparator.comparingInt(Person::getAge).reversed())
                .limit(3)
                .collect(Collectors.toList());
​
        while (!topThreeMales.stream().anyMatch(p -> p.getName().equals("陈平安"))) {
            topThreeMales = maleTeam.stream()
                    .sorted(Comparator.comparingInt(Person::getAge).reversed())
                    .limit(topThreeMales.size() + 1)
                    .collect(Collectors.toList());
        }
​
        System.out.println("男性队伍按年龄排序,取前三:");
        topThreeMales.forEach(System.out::println);
​
        // 4. 女性队伍按年龄排序,去掉前2,确保包含宁姚
        List<Person> remainingFemales = femaleTeam.stream()
                .sorted(Comparator.comparingInt(Person::getAge).reversed())
                .skip(2)
                .collect(Collectors.toList());
​
        while (!remainingFemales.stream().anyMatch(p -> p.getName().equals("宁姚"))) {
            remainingFemales = femaleTeam.stream()
                    .sorted(Comparator.comparingInt(Person::getAge).reversed())
                    .skip(femaleTeam.size() - remainingFemales.size() - 1)
                    .collect(Collectors.toList());
        }
​
        System.out.println("女性队伍按年龄排序,去掉前2:");
        remainingFemales.forEach(System.out::println);
​
        // 5. 合并两个队伍,并打印
        List<Person> combinedTeam = Stream.concat(topThreeMales.stream(), remainingFemales.stream())
                .collect(Collectors.toList());
        System.out.println("合并后的队伍:");
        combinedTeam.forEach(System.out::println);
    }
}

原文地址:https://blog.csdn.net/Elaine2391/article/details/143621982

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!