Java 8新特性Stream的常用方法总结和使用


前言

Stream 是 Java 8 引入的一个新的流式处理 API,用于对集合进行高效的操作和处理。Stream 提供了一系列方法,使得对集合的操作更加简洁、高效和易于理解


Stream常用方法

中间操作方法(返回值为Stream的方法)

中间操作不会立即产生最终结果,而是构建一个操作链。它们可以对 Stream 中的元素进行各种处理,如筛选(filter)、映射(map)、排序(sorted)。
——因为返回的Stream对象,就可以一直使用链式调用这些方法。
myList.filter(…).sorted().filter().map(…);
myList.sorted().map(…).sorted().filter(…);

——只有当执行到一个终端操作(如 reduce、collect 等)时,才会真正按照操作链依次执行中间操作,并得到最终的结果。

**filter(Predicate<T> predicate)**:用于过滤元素,返回一个新的 Stream,其中包含满足指定条件的元素。
**map()**:用于对元素进行映射,返回一个新的 Stream,其中包含将原始元素转换后的结果。
**sorted()**:用于对元素进行排序,返回一个新的 Stream,其中元素按照指定的比较器进行排序。
**limit()**:用于限制 Stream 的长度,返回一个新的 Stream,其中包含指定数量的元素。
**skip()**:用于跳过指定数量的元素,返回一个新的 Stream,其中不包含跳过的元素。
**distinct()**:用于去除重复元素,返回一个新的 Stream,其中不包含重复的元素。
**concat()**:用于连接两个或多个 Stream,返回一个新的 Stream,其中包含所有连接的元素。

终端操作(返回类型不是Stream)

**forEach(Consumer<? super T> action)**:对 Stream 中的每个元素执行指定的动作,没有返回值(返回类型为 void)。
**collect(Collector<? super T, A, R> collector)**:使用收集器进行元素的收集和处理,返回收集后的结果,具体返回值类型取决于使用的收集器所定义的类型。
**count()**:返回元素的数量,返回值类型为 long。
**reduce(BinaryOperator<T> accumulator)**:对元素进行归约操作,返回归约后的结果,具体返回值类型与元素类型相同。
**findFirst()**:查找并返回第一个元素,如果存在则返回该元素,否则返回 Optional.empty,返回值类型为 Optional<T>。
**anyMatch(Predicate<? super T> predicate)**:判断是否至少有一个元素满足条件,如果有则返回 true,否则返回 false,返回值类型为 boolean。
**allMatch(Predicate<? super T> predicate)**:判断是否所有元素都满足条件,如果是则返回 true,否则返回 false,返回值类型为 boolean。
**noneMatch(Predicate<? super T> predicate)**:判断是否没有一个元素满足条件,如果是则返回 true,否则返回 false,返回值类型为 boolean。

一、中间操作方法(返回值为Stream的方法)

1.filter 的使用(过滤操作,过滤后可能会减少数据)

//筛选出大于 5 的元素。
List<Integer> list = Arrays.asList(1, 2, 4, 5, 6, 7, 6, 3, 1, 4, 2);
list.stream().filter(n -> n > 5)
			 .forEach(m -> System.out.println("m = " + m));

2.map()的使用(过滤后数据不会减少 可能修改了某些内容)

代码如下(示例):

/**
  * 将PersonList转换为StudentList,
    并且根据Person对象组装Student对象,
     1、stdName = name
     2、Student对象中的stdNo属性由Person的id和birth组成,StdNo格式为:x-yyyymmdd,
     3、Student中stdBirth为Date类型,取出Person中的birth值(String),转换为Date赋值给Student
  */
//初始化列表
List<Person> personList = Arrays.asList(new Person(1, "叶修", "2023-09-11")
, new Person(2, "韩文清", "2022-10-1")
, new Person(3, "张佳乐", "2024-5-21"));


//转换为Student对象
List<Student> StudentsList = personList.stream().map(person ->
        {
            Student student = new Student();
            student.setStdNo(person.getId() + "-" + person.getBirth().replaceAll("-", ""));//学号由id拼接生日
            student.setStdName(person.getName());
            // 将日期字符串转换为 Date 对象
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

            try {
                Date stdBirth = dateFormat.parse(person.getBirth());
                student.setStdBirth(stdBirth);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return student;

        }
)
        .sorted(Comparator.comparing(Student::getStdBirth).reversed())//根据stdBirth排序
        .collect(Collectors.toList());

    personList.forEach(p -> System.out.println(p.toString()));
    StudentsList.forEach(s -> System.out.println(s.toString()));

3、limit & skip 的使用

代码如下(示例):

limit方法接受一个参数maxSize,表示要限制的元素数量。
skip方法接受一个参数n,表示要跳过的元素数量。

List<String> list = Arrays.asList("叶修","韩文清","张佳乐",
        "喻文州","黄少天","苏沐橙","周泽楷","王杰希","肖时钦","叶修");

//取前三个数据在控制台输出
list.stream().limit(3).forEach(System.out::println);
//跳过三个元素把剩余的元素的控制台输出
list.stream().skip(3).forEach(System.out::println);
//跳过两个元素,把剩下的元素中前两个元素在控制台输出
list.stream().skip(2).limit(2).forEach(System.out::println);
//跳过一个元素,剩下的取三个,再跳过一个【还剩下2个】,剩下的2个中再取一个
list.stream().skip(1).limit(3).skip(1).limit(1).forEach(System.out::println);

4、concat & distanct的使用

concat方法接受两个Stream对象作为参数,并返回一个新的Stream对象,其中包含了两个输入Stream中的所有元素。元素的顺序与输入Stream中的顺序相同。
distinct 方法去除流中的重复元素

List<String> list = Arrays.asList("叶修","韩文清","张佳乐",
        "喻文州","黄少天","苏沐橙","周泽楷","王杰希","肖时钦","叶修");

//取前4个组成一个流
Stream<String> limit = list.stream().limit(4);
//跳过两个数据组成一个流
Stream<String> skip = list.stream().skip(2);
//合并需求1和2流,并把结果在控制台输出
Stream.concat(limit,skip).forEach(System.out::println);
//合并需求1和2流,并把结果在控制台输出要求不能重复
Stream.concat(limit,skip).distinct().forEach(System.out::println);

二、终端操作(返回类型不是Stream)

1、forEach&&collect

forEach:遍历Stream中的元素
collect:使用收集器进行元素的收集和处理,返回收集后的结果,例如参数为Collectors.toList() 可以将Stream返回值为List对象

//初始化list
List<String> list = Arrays.asList("叶修","韩文清","张佳乐",
        "喻文州","黄少天","苏沐橙","周泽楷","王杰希","肖时钦","叶修");
//forEach 遍历列表中的元素 返回值为void
list.stream().forEach(name -> System.out.println("name = " + name));
//collect 获取前4个生成新的list
List<String> collect = list.stream().limit(4).collect(Collectors.toList());
collect.stream().forEach(item-> System.out.println("collect ->item = " + item));

2、reduce、max、min、count 聚合函数

reduce:对Stream中的元素进行聚合求值,返回处理的结果,具体返回值类型与元素类型相同。
Optional max :根据自定义的比较器,返回最大值;
Optional min : 根据自定义的比较器,返回最小值。
count()返回元素的个数

//reduce 对Stream中的元素进行聚合求值,返回处理的结果,具体返回值类型与元素类型相同。
 List<Integer> number = Arrays.asList(1, 2, 3, 4, 5);
// 使用Stream.reduce()方法计算数组元素的总和
 int sum = number.stream().reduce(0, (a, b) -> a + b);
 System.out.println("数组元素的总和为:" + sum);

//使用Stream.max()方法获取元素中的最大值
Integer maxNumber = number.stream().max(Comparator.comparingInt(o -> o)).get();
System.out.println("maxNumber = " + maxNumber);

//使用Stream.max()方法获取元素中的最大值
Integer minNumber = number.stream().min((o1, o2) -> o1 - o2).get();
System.out.println("minNumber = " + minNumber);

//统计元素的个数
long count = number.stream().count();
System.out.println("numbers的个数 = " + count);

3、findFirst

findFirst 查找满足条件的一条数,返回一个Optional对象

List<String> list = Arrays.asList("叶修","韩文清","张佳乐",
        "喻文州","黄少天","苏沐橙","周泽楷","王杰希","肖时钦","叶修");
//查找匹配条件的第一条数据
Optional<String> theName = list.stream().filter(name -> name.equals("叶修")).findFirst();
//判断是否找到
if (theName.isPresent()) {
    System.out.println("theName.get() = " + theName.get());
} else {
    System.out.println("没有找到");
} 

4、anyMatch 、allMatch、noneMatch

anyMatch(Predicate p): 检查流中是否存在至少一个元素满足指定的条件p。如果存在,则返回true;否则返回false。
allMatch(Predicate p): 检查流中是否所有元素都满足指定的条件p。如果所有元素都满足,则返回true;否则返回false。
noneMatch(Predicate p): 检查流中是否不存在任何一个元素满足指定的条件p。如果不存在,则返回true;否则返回false。

List<String> list = Arrays.asList("叶修","韩文清","张佳乐",
        "喻文州","黄少天","苏沐橙","周泽楷","王杰希","肖时钦","叶修");
// 使用 anyMatch 方法,只要有一个条件满足的都会返回ture
boolean anyMatch = list.stream().anyMatch(f -> f.equals("叶修"));
System.out.println("anyMatch: " + anyMatch); // true

// 使用 allMatch 方法  所有元素都满足,才能返回true
boolean allMatch = list.stream().allMatch(f -> f.length() == 3); //字符长度是否都为3
System.out.println("allMatch: " + allMatch); // false

// 使用 noneMatch 方法 所有元素都不满足才能返回true 只要有一个满足的情况都会返回false
boolean noneMatch = list.stream().noneMatch(f -> f.length() == 1);
System.out.println("noneMatch: " + noneMatch); // true

总结

Stream API提供了一种高效且易于阅读的方式来操作数据,特别是在需要对数据进行过滤、映射、排序、聚合等操作时。

参考链接

java-Stream流的常见方法

  • 22
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值