Stream流常用操作

一、中间操作

中间操作是返回一个新的流,并在返回的流中包含所有之前的操作结果。它们总是延迟计算,这意味着它们只会在终止操作时执行,这样可以最大限度地优化资源使用。

1. filter(过滤)

filter()方法接受一个谓词(一个返回boolean值的函数),并返回一个流,其中仅包含通过该谓词的元素。
eg:从一个数组中筛选出长度大于5的元素。

java 复制代码
@Test
public void testFilter() {
    List<String> names = Arrays.asList("Chengdu", "Shanghai", "Changsha", "Wuhan", "Hangzhou");
    List<String> collect = names.stream().filter(item -> item.length() > 5).collect(Collectors.toList());
    System.out.println(collect);
}

2. map(转换)

map()方法可将一个流的元素转换为另一个流。它接受一个函数,该函数映射流中的每个元素到另一个元素。
eg:对数字列表中的每个元素进行乘以 2 的操作,并将操作后的结果保存到新的列表中。

java 复制代码
@Test
public void testMap() {
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    List<Integer> collect = numbers.stream().map(n -> {
        n = n * 2;
        return n;
    }).collect(Collectors.toList());
    
    for (Integer integer : collect) {
        System.out.println("integer = " + integer);
    }
}


eg:将结果转换为Map。

java 复制代码
@Test
public void testMapToMap() {
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    Map<Byte, Integer> collect = numbers.stream().collect(Collectors.toMap(Integer::byteValue, item -> item * 2, (val1, val2) -> val2));

    for (Map.Entry<Byte, Integer> byteIntegerEntry : collect.entrySet()) {
        Byte key = byteIntegerEntry.getKey();
        System.out.println("key = " + key + ",Value = " + byteIntegerEntry.getValue());
    }
}
  1. 首先创建了一个包含数字 1~5 的列表。然后利用 stream() 方法将列表转换成 Stream 对象。
  2. 接下来调用 collect(Collectors.toMap(...)) 方法将 Stream 转换成 Map<Byte, Integer>
  3. toMap ()方法中,以每个整数的字节值为键,该整数乘以 2 为值,当遇到重复的键时取最后一个值。(这里实际上可以用任何能区分不同键的方式作为第一个参数,而不一定是 Integer::byteValue
  4. 最后,在 for 循环中遍历了这个 Map 并打印出每个键值对的内容。

3. sorted(排序)

sorted()方法可对流进行排序。它可以接受一个Comparator参数,也可以使用自然排序Ordering.natural()。默认排序是按升序排序。
eg:对数组元素排序。

java 复制代码
@Test
public void testSorted() {
    int[] numbers = {5, 2, 8, 3, 7};
    int[] sortedNumbers = Arrays.stream(numbers).sorted().toArray();
    System.out.println(Arrays.toString(sortedNumbers));
}
  1. 首先创建了一个包含整数的数组numbers。
  2. 然后使用Arrays.stream()方法将其转化为一个IntStream流。
  3. 接下来使用sorted()方法对流中的元素进行排序操作,返回一个新的排序后的IntStream流。
  4. 最后,使用toArray()方法将排序后的结果转换为一个新的int类型数组sortedNumbers,并使用Arrays.toString()方法将结果输出到控制台。

4. distinct(去重)

distinct()方法从流中返回所有不同的元素。在内部,它使用equals()方法来比较元素是否相同。因此,我们需要确保equals()方法已正确实现。
eg:去除list集合中重复的元素。

java 复制代码
@Test
public void testDistinct() {
    List<Integer> numbers = Arrays.asList(1, 2, 3, 2, 1);
    List<Integer> collect = numbers.stream().distinct().collect(Collectors.toList());
    System.out.println(collect);
}
  1. 首先创建了一个包含整数的List集合numbers,其中包含了若干个重复的整数。
  2. 接下来使用Stream()方法将其转化为一个Stream流。使用distinct()方法对流中的元素进行去重操作,返回一个新的不包含重复元素的Stream流collect。
  3. 最后使用collect()方法将去重后的结果转换成一个List集合,并使用System.out.println()方法输出到控制台。

使用Stream流中的distinct()方法可以快速地对集合中的重复元素进行去重处理。在这段代码中,集合中的元素都是整数,使用distinct()方法去除了所有重复的整数,返回一个新的元素不重复且顺序不变的List集合。

5. limit(限制)

limit()方法可以将流限制为指定的元素数。
eg:输出数组中前三个数。

java 复制代码
@Test
public void testLimit() {
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
    List<Integer> collect = numbers.stream().limit(3).collect(Collectors.toList());
    System.out.println(collect);
}
  1. 首先创建了一个包含整数的List集合numbers,其中包含了10个整数。
  2. 接下来使用Stream()方法将其转化为一个Stream流。使用limit()方法对流中的元素进行限制操作,仅保留前3个元素,返回一个新的只包含前3个元素的Stream流collect。
  3. 最后使用collect()方法将限制操作后的结果转化为一个新的List集合,并使用System.out.println()方法输出到控制台。

6. skip(跳过)

skip()方法可跳过前N个元素。
eg:跳过数组的前三个数。

java 复制代码
@Test
public void testSkip() {
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
    List<Integer> collect = numbers.stream().skip(3).collect(Collectors.toList());
    System.out.println(collect);
}
  1. 首先创建了一个包含整数的List集合numbers,其中包含了5个整数。
  2. 接下来使用Stream()方法将其转化为一个Stream流。使用skip()方法对流中的元素进行跳过操作,跳过前2个元素,返回一个新的不包含前2个元素的Stream流collect。
  3. 最后使用collect()方法将跳过操作后的结果转化为一个新的List集合,并使用System.out.println()方法输出到控制台。

7. peek(展示)

peek()方法可以用于在Stream流中获取元素同时执行一些操作,如打印、调试、观察等。通常会与其他的方法联合使用。
eg:输出元素。

java 复制代码
 @Test
public void testPeek() {
    List<String> names = Arrays.asList("Chengdu", "Shanghai", "Changsha", "Guangzhou");
    List<String> filteredNames = names.stream()
            .peek(System.out::println)
            .filter(name -> name.startsWith("C"))
            .peek(name -> System.out.println("Filtered value: " + name))
            .collect(Collectors.toList());
    System.out.println("-----------------------------------------------------------------");
    System.out.println(filteredNames);
}
  1. 首先创建了一个列表 names 包含四个字符串元素,使用流式操作处理这个列表。
  2. 然后使用 peek() 方法将每个元素打印到控制台,使用 filter() 方法过滤掉不符合条件的元素,即不以字母 C 开头的字符串。
  3. 接下来再次使用 peek() 方法将符合条件的字符串打印到控制台,以便验证过滤操作的效果。
  4. 最后使用 collect() 方法将符合条件的字符串收集到一个新的列表 filteredNames 中,并输出该列表。

二、终止操作

终止操作返回一个结果或副作用(例如:显示控制台输出),并将流关闭。

1. forEach(遍历)

forEach()方法可将给定的方法应用于流中的每个元素。该方法是一种消费流的方式,不会返回值。
eg:数组元素遍历。

java 复制代码
@Test
public void testForEach() {
    List<String> names = Arrays.asList("Chengdu", "Shanghai", "Wuhan", "Changsha");
    names.stream().forEach(System.out::println);
}
  1. 创建了一个包含四个字符串元素的列表 names。
  2. 使用流式操作将每个元素打印到控制台。具体来说,它使用 forEach() 方法遍历列表中的所有元素,并对每个元素执行打印操作。

2. collect(收集)

collect()方法可以将流中的元素收集到一个集合中。一般与其他方法配合使用。
eg:收集数组中能被25整除的数。

java 复制代码
@Test
public void testCollect() {
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    List<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());
    System.out.println(evenNumbers);
}
  1. 首先创建了一个包含整数的列表 numbers,使用流式操作筛选出所有偶数。
  2. 然后将它们收集到一个新的列表 evenNumbers 中,并打印输出。

这里使用了 filter() 方法过滤掉所有奇数元素,只保留所有偶数元素,并使用 collect() 方法将它们收集到一个新的列表 evenNumbers 中。只有偶数元素被保留在了新列表 evenNumbers 中,而奇数元素全部被过滤掉了。而且,在筛选偶数元素时,使用了 lambda 表达式 n -> n % 2 == 0,其中 % 表示取模操作,判断当前数是否为偶数。如果 n % 2 的结果是 0,就把 n 这个数保留下来,否则就过滤掉。

3. count(计数)

count()方法可以返回流中的元素数。
eg:计算数组元素个数。

java 复制代码
@Test
public void testCount() {
    List<String> names = Arrays.asList("Chengdu", "Guangzhou", "Wuhan", "Changsha");
    long count = names.stream().count();
    System.out.println(count);
}
  1. 首先创建了一个包含四个字符串元素的列表 names,使用流式操作计算出它包含的元素数量(即列表大小),并将该数量打印到控制台。

这里使用了 count() 方法统计列表中元素的个数。count() 方法返回的是一个 long 类型的值,表示列表中元素的个数。因为列表 names 包含了四个元素,所以 count() 方法返回值为 4,最终被打印输出到了控制台。

4. reduce(聚合)

reduce()方法可以将流元素聚合为单个结果。它接受一个BinaryOperator参数作为累加器。
eg:计算数组元素的和。

java 复制代码
@Test
public void testReduce() {
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    Optional<Integer> sum = numbers.stream().reduce((a, b) -> a + b);
    System.out.println(sum);
}
  1. 首先创建了一个包含整数的列表 numbers,使用流式操作将它们累加起来得到总和,并将结果打印输出。

这里使用了 reduce() 方法对列表中的所有元素进行累加操作。reduce() 方法接收一个 BinaryOperator 函数作为参数,用于指定如何处理相邻的两个元素并返回一个新的结果值。reduce() 方法返回的是一个 Optional 类型的值,表示结果可能存在也可能不存在(例如当列表为空时)。由于列表 numbers 包含 1 到 5 共五个元素,因此 reduce() 方法的操作过程如下:

1 + 2 = 3

3 + 3 = 6

6 + 4 = 10

10 + 5 = 15

最终得到的结果 15 被包装成 Optional 类型的对象并打印输出到控制台。

5. anyMatch(任意匹配)

anyMatch()方法如果至少有一个元素与给定的谓词匹配,则返回true。
eg:判断数组元素中是否有以W开头的,有返回true,无返回false。

java 复制代码
@Test
public void anyMatch() {
    List<String> names = Arrays.asList("Chengdu", "Guangzhou", "Wuhan", "Changsha");
    boolean anyStartsWithB = names.stream().anyMatch(name -> name.startsWith("W"));
    System.out.println(anyStartsWithB);
}
  1. 首先创建了一个包含四个字符串元素的列表 names,使用流式操作检查其中是否有任意一个元素以字母 "W" 开头,并将检查结果(布尔值)打印输出。

这里使用了 anyMatch() 方法匹配列表中的所有元素,并依次对每个元素执行指定的谓词操作(这里是以 "W" 开头),只要有一个元素符合条件,就返回 true,否则返回 false。列表 names 中包含了一个以字母 "W" 开头的元素 "Wuhan",因此 anyMatch() 方法返回 true,最终被打印输出到了控制台。

6. oneMatch(无匹配)

noneMatch()方法,如果没有任何元素与给定谓词匹配,则返回true。
eg:判断数组元素中是否有以H开头的,无返回true,有返回false。

java 复制代码
@Test
public void testToneMatch() {
    List<String> names = Arrays.asList("Chengdu", "Guangzhou", "Wuhan", "Changsha");
    boolean noneStartsWithB = names.stream().noneMatch(name -> name.startsWith("H"));
    System.out.println(noneStartsWithB);
}
  1. 首先创建了一个包含四个字符串元素的列表 names,使用流式操作检查其中是否没有任意一个元素以字母 "H" 开头,并将检查结果(布尔值)打印输出。

这里使用了 noneMatch() 方法匹配列表中的所有元素,并依次对每个元素执行指定的谓词操作(这里是以 "H" 开头),只有当所有元素都不符合条件时,才返回 true,否则返回 false。列表 names 中不包含任何一个以字母 "H" 开头的元素,因此 noneMatch() 方法返回 true,最终被打印输出到了控制台。

相关推荐
大数据编程之光13 分钟前
Flink Standalone集群模式安装部署全攻略
java·大数据·开发语言·面试·flink
爪哇学长27 分钟前
双指针算法详解:原理、应用场景及代码示例
java·数据结构·算法
ExiFengs31 分钟前
实际项目Java1.8流处理, Optional常见用法
java·开发语言·spring
paj12345678932 分钟前
JDK1.8新增特性
java·开发语言
捂月39 分钟前
Spring Boot 深度解析:快速构建高效、现代化的 Web 应用程序
前端·spring boot·后端
繁依Fanyi43 分钟前
简易安卓句分器实现
java·服务器·开发语言·算法·eclipse
慧都小妮子1 小时前
Spire.PDF for .NET【页面设置】演示:打开 PDF 时自动显示书签或缩略图
java·pdf·.net
m51271 小时前
LinuxC语言
java·服务器·前端
IU宝1 小时前
C/C++内存管理
java·c语言·c++
瓜牛_gn1 小时前
依赖注入注解
java·后端·spring