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,最终被打印输出到了控制台。

相关推荐
喂完待续7 分钟前
【序列晋升】29 Spring Cloud Task 微服务架构下的轻量级任务调度框架
java·spring·spring cloud·云原生·架构·big data·序列晋升
benben04410 分钟前
ReAct模式解读
java·ai
java水泥工42 分钟前
校园管理系统|基于SpringBoot和Vue的校园管理系统(源码+数据库+文档)
数据库·vue.js·spring boot
轮到我狗叫了1 小时前
牛客.小红的子串牛客.kotori和抽卡牛客.循环汉诺塔牛客.ruby和薯条
java·开发语言·算法
令狐少侠20111 小时前
maven settings.xml文件的各个模块、含义以及它们之间的联系
xml·maven
Volunteer Technology2 小时前
三高项目-缓存设计
java·spring·缓存·高并发·高可用·高数据量
栗子~~2 小时前
bat脚本- 将jar 包批量安装到 Maven 本地仓库
java·maven·jar
Mr.Entropy3 小时前
ecplise配置maven插件
java·maven
叙白冲冲3 小时前
tomcat 为啥能一直运行?不像方法那样结束?
java·tomcat
CoderYanger3 小时前
MySQL数据库——3.2.1 表的增删查改-查询部分(全列+指定列+去重)
java·开发语言·数据库·mysql·面试·职场和发展