Stream 流用法详解


共计 5918 个字符,预计需要花费 15 分钟才能阅读完成。

简介

Stream 是 Java 8 引入的一个功能强大的流式处理 API。它允许我们以声明性的方式操作集合(数组、集合等)的元素。通过使用 Stream,我们可以将多个操作连接起来,形成一个流水线,从而简化代码并提高可读性。

Stream 类中包含的方法,可以进行数据筛选、转换、排序、去重、限制、跳过、归约、统计、匹配、查找和遍历等操作。

数据筛选和转换:

  • filter(Predicate<T> predicate):根据指定条件过滤流中的元素。
  • map(Function<T, R> mapper):对流中的元素进行映射操作,转换为另一种类型。
  • flatMap(Function<T, Stream<R>> mapper):对流中的元素进行映射操作,将每个元素映射为一个流,并将所有流的元素合并成一个流。

数据排序和去重:

  • sorted():对流中的元素进行排序操作。
  • distinct():去除流中的重复元素。

数据归约和统计:

  • count():返回流中的元素数量。
  • reduce(BinaryOperator<T> accumulator):对流中的元素进行归约操作,得到一个最终结果。
  • collect(Collector<T, A, R> collector):将流中的元素收集到一个集合或其他数据结构中。

数据匹配和查找:

  • max(Comparator<T> comparator):返回流中的最大元素。
  • min(Comparator<T> comparator):返回流中的最小元素。
  • findFirst():返回流中的第一个元素。
  • findAny():返回流中的任意一个元素。
  • anyMatch(Predicate<T> predicate):检查流中是否存在满足条件的元素。
  • allMatch(Predicate<T> predicate):检查流中的所有元素是否都满足条件。
  • noneMatch(Predicate<T> predicate):检查流中是否没有任何元素满足条件。

数据限制和跳过:

  • limit(long maxSize):限制流中元素的数量。
  • skip(long n):跳过流中的前 n 个元素。

其他方法:

  • forEach(Consumer<T> action):对流中的每个元素执行指定的操作。

使用

1. 数据筛选和转换

数据的筛选和转换用得最多的当属 filter 和 map 方法。

1.1 filter

根据指定的条件过滤流中的元素。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> evenNumbers = numbers.stream()
                                   .filter(n -> n % 2 == 0)
                                   .collect(Collectors.toList());
System.out.println(evenNumbers); // 输出结果:[2, 4, 6]

1.2 map

对流中的元素进行映射操作,将其转换为另一种类型。

List<String> names = Arrays.asList("John", "Jane", "Tom");
List<Integer> nameLengths = names.stream()
                                 .map(String::length)
                                 .collect(Collectors.toList());
System.out.println(nameLengths); // 输出结果:[4, 4, 3]

2. 数据排序和去重

数据的排序和去重用得也是比较多的方法。

2.1 sorted

对流中的元素进行排序操作。

List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 6);
List<Integer> sortedNumbers = numbers.stream()
                                     .sorted()
                                     .collect(Collectors.toList());
System.out.println(sortedNumbers);v // 输出结果:[1, 2, 5, 6, 8]

2.2 distinct

去除流中重复的元素。

List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 4, 5);
List<Integer> distinctNumbers = numbers.stream()
                                       .distinct()
                                       .collect(Collectors.toList());
System.out.println(distinctNumbers); // 输出结果:[1, 2, 3, 4, 5]

3. 数据归约和统计

3.1 count

返回流中的元素数量。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
long count = numbers.stream()
                    .count();
System.out.println(count); // 输出结果:5

3.2 reduce

对流中的元素进行归约操作,将流中的元素通过指定的操作进行组合,得到一个最终结果。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> sum = numbers.stream()
                               .reduce((a, b) -> a + b);
System.out.println(sum.orElse(0)); // 输出结果:15

3.3 collect

用于将流中的元素收集到一个集合或其他数据结构中。

将流元素收集到 List 中

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> collectedList = numbers.stream()
                                     .collect(Collectors.toList());
System.out.println(collectedList);

将流元素收集到 Set 中

List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 4, 5);
Set<Integer> collectedSet = numbers.stream()
                                   .collect(Collectors.toSet());
System.out.println(collectedSet);

将流元素收集到 Map 中

List<String> names = Arrays.asList("John", "Jane", "Tom");
Map<String, Integer> nameLengthMap = names.stream()
                                          .collect(Collectors.toMap(
                                              name -> name,
                                              name -> name.length()
                                          ));
System.out.println(nameLengthMap); // 输出结果:{John=4, Jane=4, Tom=3}

根据某个属性对流中的元素进行分组

Person 类

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

可以根据年龄对 Person 对象进行分组:

List<Person> persons = Arrays.asList(
    new Person("John", 25),
    new Person("Jane", 30),
    new Person("Tom", 22),
    new Person("Alice", 30)
);

Map<Integer, List<Person>> ageGroupMap = persons.stream()
                                                .collect(Collectors.groupingBy(Person::getAge));

System.out.println(ageGroupMap); // 输出结果:{22=[Person{name='Tom', age=22}], 25=[Person{name='John', age=25}], 30=[Person{name='Jane', age=30}, Person{name='Alice', age=30}]}

将流元素收集到自定义的容器中

自定义的容器类 PersonContainer

public class PersonContainer {
    private List<Person> persons = new ArrayList<>();

    public void addPerson(Person person) {
        persons.add(person);
    }

    public List<Person> getPersons() {
        return persons;
    }
}

示例代码:

List<Person> persons = Arrays.asList(
    new Person("John", 25),
    new Person("Jane", 30),
    new Person("Tom", 22)
);

PersonContainer container = persons.stream()
                                   .collect(
                                       PersonContainer::new,
                                       PersonContainer::addPerson,
                                       PersonContainer::addPerson
                                   );

List<Person> collectedPersons = container.getPersons();
System.out.println(collectedPersons); // 输出结果:[Person{name='John', age=25}, Person{name='Jane', age=30}, Person{name='Tom', age=22}]

4. 数据匹配和查找

4.1 max

返回流中的最大的元素,返回是一个 Optional 类。

List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 6);
Optional<Integer> maxNumber = numbers.stream()
                                     .max(Integer::compareTo);
System.out.println(maxNumber.orElse(0)); // 输出 8

4.2 min

返回流中的最小的元素,返回是一个 Optional 类。

List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 6);
Optional<Integer> minNumber = numbers.stream()
                                     .min(Integer::compareTo);
System.out.println(minNumber.orElse(0)); // 输出 1

4.3 findFirst

返回流中的第一个元素(按照流的遍历顺序),返回是一个 Optional 类。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> firstNumber = numbers.stream()
                                       .findFirst();
System.out.println(firstNumber.orElse(0)); // 输出 1

4.4 findAny

返回流中的任意一个元素,返回是一个 Optional 类。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> anyNumber = numbers.stream()
                                     .findAny();
System.out.println(anyNumber.orElse(0)); // 输出结果:1(可能的结果因为随机性而有所不同)

4.5 anyMatch

检查流中是否存在满足给定条件的元素,返回是一个布尔值。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean hasEvenNumber = numbers.stream()
                               .anyMatch(n -> n % 2 == 0);
System.out.println(hasEvenNumber); // 输出结果:true

4.6 anyMatch

检查流中的所有元素是否都满足给定条件,返回是一个布尔值。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean allEvenNumbers = numbers.stream()
                                .allMatch(n -> n % 2 == 0);
System.out.println(allEvenNumbers); // 输出结果:false

4.7 noneMatch

检查流中是否没有任何元素满足给定条件。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean noNegativeNumbers = numbers.stream()
                                   .noneMatch(n -> n < 0);
System.out.println(noNegativeNumbers); // 输出结果:true

5. 数据限制和跳过

5.1 limit

限制流中元素的数量。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> limitedNumbers = numbers.stream()
                                      .limit(3)
                                      .collect(Collectors.toList());
System.out.println(limitedNumbers); // 输出结果:[1, 2, 3]

5.2 skip

跳过流中的前 n 个元素。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> skippedNumbers = numbers.stream()
                                      .skip(2)
                                      .collect(Collectors.toList());
System.out.println(skippedNumbers);

6. 其他方法

6.1 forEach

对流中的每个元素执行指定的操作。

List<String> names = Arrays.asList("John", "Jane", "Tom");
names.stream()
     .forEach(System.out::println);

提醒:本文发布于494天前,文中所关联的信息可能已发生改变,请知悉!

Tips:清朝云网络工作室

阅读剩余
THE END