别死脑筋,赶紧学起来!Java之Stream API 常用方法使用,让开发简单起来!

222 阅读5分钟

原创作者,公众号【IT技术馆】,欢迎关注公众号,转载文章请注明出处哦。

Java 的 Stream API 是 Java 8 引入的一个关键特性,提供了一种声明性的方式来处理数据集合(如集合、数组等)。通过 Stream API,你可以以简洁、高效的方式执行复杂的查询、过滤、转换和聚合操作。以下是对 Stream API 的详细解释和一些示例。

Java Stream API支持的功能

功能描述
filter过滤流中的元素,根据条件只留下满足条件的元素
map将流中的每个元素映射成其他形式,结果是一个包含映射后结果的新流
sorted确保流中的元素在消费时的顺序按照自然顺序或自定义Comparator排序
collect将流转换为其他形式,如List、Set或Map,或者是自定义的收集器
forEach遍历流中的每个元素并执行给定的操作
reduce通过重复处理其元素来将流减少到单个汇总结果
anyMatch检查流中的元素是否有一个满足给定的条件
allMatch检查流中的元素是否全部满足给定条件
noneMatch检查流中的元素是否没有满足给定条件的
findFirst返回流中的第一个元素,如果流为空,则返回空的Optional
limit截断流,使其最大长度不超过给定数量
skip跳过流中的前n个元素,返回包含余下元素的新流

使用Java Stream API的优势

功能Java Stream API传统集合操作
数据处理模式声明式,支持函数式编程命令式,代码较为复杂
内存效率更高,因为它是在流上直接操作低,需要复制到新的数据结构
并发处理内建支持并发处理手动处理并发
可读性高,流操作可链式调用低,循环和条件判断多
使用场景数据集合操作,大数据处理小数据量操作

常用的 Java Stream API功能

Java中的Stream API是Java 8引入的一个关键抽象概念,它允许你以声明性方式处理数据集合(如数组、列表等)。Stream API提供了一套丰富的操作来过滤、转换、聚合数据等。以下是Stream API中一些常用的API介绍及示例:

1. 创建Stream

  • 从集合创建:可以使用Collection接口中的stream()方法。
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();
  • 从数组创建:可以使用Arrays.stream(T[] array)方法。
int[] array = {1, 2, 3};
Stream<Integer> stream = Arrays.stream(array);
  • 创建空Stream:可以使用Stream.empty()方法。
Stream<String> emptyStream = Stream.empty();
  • 使用Stream.of:可以从一组值中创建Stream。
Stream<String> streamOfValues = Stream.of("a", "b", "c");
  • 使用Stream.builder:可以使用Stream.Builder来构建Stream。
Stream.Builder<String> builder = Stream.builder();
builder.add("a");
builder.add("b");
Stream<String> streamFromBuilder = builder.build();

2. 中间操作

中间操作返回一个新的Stream,并且它们是惰性求值的,只有在调用终端操作时才会执行。

  • filter:过滤元素。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<String> filteredNames = names.stream()
    .filter(name -> name.startsWith("A"))
    .collect(Collectors.toList());
// 输出: ["Alice"]
  • map:将每个元素映射为另一个类型。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<Integer> nameLengths = names.stream()
    .map(String::length)
    .collect(Collectors.toList());
// 输出: [5, 3, 7]
  • sorted:对流中的元素进行排序。
List<String> names = Arrays.asList("Bob", "Alice", "Charlie");
List<String> sortedNames = names.stream()
    .sorted()
    .collect(Collectors.toList());
// 输出: ["Alice", "Bob", "Charlie"]
  • distinct:去除流中的重复元素。
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4);
List<Integer> distinctNumbers = numbers.stream()
    .distinct()
    .collect(Collectors.toList());
// 输出: [1, 2, 3, 4]
  • limit:截取流中的前n个元素。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> limitedNumbers = numbers.stream()
    .limit(3)
    .collect(Collectors.toList());
// 输出: [1, 2, 3]
  • skip:跳过前n个元素。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> skippedNumbers = numbers.stream()
    .skip(2)
    .collect(Collectors.toList());
// 输出: [3, 4, 5]

3. 终端操作

终端操作产生结果或者副作用,并且执行后会结束流。

  • forEach:对流中的每个元素执行某种操作。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream().forEach(System.out::println);
// 输出: Alice, Bob, Charlie
  • collect:将流中的元素收集到某种结果中。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<String> collectedNames = names.stream()
    .collect(Collectors.toList());
// 输出: ["Alice", "Bob", "Charlie"]
  • reduce:对流中的元素进行累积操作。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
int sum = numbers.stream()
    .reduce(0, Integer::sum);
// 输出: 10
  • count:返回流中元素的个数。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
long count = names.stream().count();
// 输出: 3
  • findFirst:返回流中的第一个元素(作为Optional对象)。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Optional<String> firstName = names.stream()
    .findFirst();
// 输出: Optional["Alice"]
  • anyMatch:检查流中是否有任意元素匹配给定的条件。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
boolean hasAlice = names.stream()
    .anyMatch(name -> name.equals("Alice"));
// 输出: true

4. 其他高级操作

  • flatMap:将流中的每个元素映射为另一个流,并将结果合并为一个流。
List<String> names = Arrays.asList("Alice", null, "Bob", null, "Charlie");
List<String> nonNullNames = names.stream()
    .flatMap(Stream::ofNullable)
    .collect(Collectors.toList());
// 输出: ["Alice", "Bob", "Charlie"]
  • iterate:创建无限的序列流。
Stream.iterate(0, n -> n + 2)
    .limit(10)
    .forEach(System.out::println);
// 输出: 0, 2, 4, 6, 8, 10, 12, 14, 16, 18
  • collectingAndThen:对收集器的结果执行特殊类型的转换。
List<String> fruits = Arrays.asList("apple", "banana", "orange");
Map<Integer, String> result = fruits.stream()
    .collect(Collectors.collectingAndThen(
        Collectors.toMap(fruits::indexOf, String::toUpperCase),
        Collections::unmodifiableMap
    ));
// 输出: {0="APPLE", 1="BANANA", 2="ORANGE"}
  • dropWhiletakeWhile(Java 9+):连续处理流。
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7);
numbers.stream()
    .dropWhile(n -> n < 3)
    .takeWhile(n -> n < 6)
    .forEach(System.out::println);
// 输出: 3, 4, 5
  • IntStream:用于快速生成整数流。
IntStream.range(1, 5).forEach(System.out::println);
// 输出: 1, 2, 3, 4
IntStream.rangeClosed(1, 5).forEach(System.out::println);
// 输出: 1, 2, 3, 4, 5
  • teeing(Java 12+):在元素流上一起应用两个单独的收集器。
Stream<Integer> nums = Stream.of(1, 2, 3, 4, 5);
Map<String, Integer> collect = nums.collect(Collectors.teeing(
    Collectors.maxBy(Integer::compareTo),
    Collectors.minBy(Integer::compareTo),
    (e1, e2) -> Map.of("min", e1.get(), "max", e2.get())
));
// 输出: {max=5, min=1}
  • concat:连接两个流并生成一个新流。
Stream<Integer> stream1 = Stream.of(1, 2, 3);
Stream<Integer> stream2 = Stream.of(4, 5, 6);
Stream.concat(stream1, stream2).forEach(System.out::println);
// 输出: 1, 2, 3, 4, 5, 6
  • partitioningBy:对流进行分组。
Stream<String> fruits = Stream.of("apple", "banana", "orange", "grape");
Map<Boolean, List<String>> result = fruits.collect(Collectors.partitioningBy(f -> f.length() > 5));
// 输出