JAVA 8 Stream 集合的基本

本文详细介绍了JAVA 8的Stream流,包括其概念、创建方式和多种操作,如筛选、去重、聚合、映射、归约、统计、分组、接合、排序等。通过实例展示了如何在实践中应用这些操作,例如使用filter、distinct、reduce等方法对集合进行处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、什么是Stream流

Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作,比如:筛选、排序、聚合等。

Stream有三大特性:

1.stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果。
2.stream不会改变数据源,通常情况下会产生一个新的集合或一个值。
3.stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行。

Stream可以由数组或集合创建,对流的操作分为两种:

1.中间操作,每次返回一个新的流,可以有多个。
2.终端操作,每个流只能进行一次终端操作,终端操作结束后流无法再次使用。终端操作会产生一个新的集合或值。

 

二、Stream创建

1.Stream创建的两种方式:

1.1.串行流

        串行流上的操作是在一个线程中依次完成

1.2.并行流

          并行流则是在多个线程上同时执行 

          所以并行流的效率比串行流高。

        List<String> list = Arrays.asList("code", "wang", "codeWang");
        // 创建一个顺序流
        Stream<String> stream = list.stream();
        // 创建一个并行流
        Stream<String> parallelStream = list.parallelStream();

 2.Stream的三个静态方法:of()、iterate()、generate()

// of()方法 返回元素的顺序流
Stream.of(1, 2, 3).forEach(System.out::println);
// iterate()方法,第一个参数是初始值,第二个参数是一个方法,对每个元素进行操作得到新值
// 这个方法获取的是无限流,需要借助limit() 方法来截取
Stream.iterate(1, (x) -> x + 4).limit(2).forEach(System.out::println);
// generate() 方法  返回无限无序流
// Stream.generate(new Random()::nextBoolean) 随机Boolean类型
// Stream.generate(new Random()::nextInt) 随机Int类型
Stream.generate(Math::random).limit(2).forEach(System.out::println);

 of方法结果: 1 2 3
iterate方法结果: 1 5
generate方法结果: 0.792347429124145  0.19113911202391165

三、Stream操作

3.1、筛选 / 去重 / 匹配(filter() / distinct() / find() / match()) 

 List<Integer> list = Arrays.asList(1, 2, 3, 4, 2, 1, 6, 7, 8, 9, 10);
 // 去重
list.stream().distinct().forEach(System.out::print);
// 满足条件 匹配第一个
Optional<Integer> findFirst = list.stream().filter(x -> x > 3).findFirst();
// 匹配任意(适用于并行流)
Optional<Integer> findAny = list.parallelStream().filter(x -> x > 6).findAny();
// 是否包含符合特定条件的元素
boolean anyMatch = list.stream().anyMatch(x -> x < 6);
System.out.println("匹配第一个:" + findFirst.get());
System.out.println("匹配任意:" + findAny.get());
System.out.println("是否包含符合条件的元素:" + anyMatch);

 结果输出

filter筛选出集合中大于3的元素: 4 6 7 8 9 10 6
distinct去重: 1 2 3 4 6 7 8 9 10
匹配第一个:4
匹配任意:7
是否包含符合条件的元素:true

 3.2、聚合(max() / min() / count())

       3.2.1、String集合中最长的元素。

List<String> stringList = Arrays.asList("code", "wang", "codeWang", "coderWang");
Optional<String> stringMax = stringList.stream().max(Comparator.comparing(String::length));
System.out.println("String集合中最长的元素:"+stringMax.get());

 String集合中最长的元素:coderWang

      3.2.2、Integer集合中的最大值。

List<Integer> integerList = Arrays.asList(5, 2, 9, 4, 16, 6);
// 自然排序
Optional<Integer> integerMax = integerList.stream().max(Integer::compareTo);
System.out.println("Integer集合中的最大值:" + integerMax.get());

Integer集合中的最大值:16

       3.2.3、 Integer集合中的最小值。

        List<Integer> integerList = Arrays.asList(5, 2, 9, 4, 16, 6);
        // 自定义排序
        Optional<Integer> integerMin = integerList.stream().min(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);
            }
        });
       System.out.println("Integer集合中的最小值:" + integerMin.get());

Integer集合中的最小值:2

      3.2.4、获取学生中成绩最高的学生

     (本文有关实体类操作都是基于此类

   //    姓名
    private String name;
    //    年龄
    private Integer age;
    //    分数
    private Double score;
    //    学科
    private String subject;

    public List<UserEntity> createList() {
        List<UserEntity> userList = new ArrayList<>();
        userList.add(new UserEntity("姬如雪", 15, 96.5, "语文"));
        userList.add(new UserEntity("女帝", 18, 96.0, "语文"));
        userList.add(new UserEntity("李星云", 16, 85.5, "语文"));
        userList.add(new UserEntity("姬如雪", 15, 92.5, "数学"));
        userList.add(new UserEntity("女帝", 18, 95.0, "数学"));
        userList.add(new UserEntity("李星云", 16, 90.5, "数学"));
        return userList;
    }

    public UserEntity() {
    }

    public UserEntity(String name, Integer age, Double score, String subject) {
        this.name = name;
        this.age = age;
        this.score = score;
        this.subject = subject;
    }
UserEntity userEntity=new UserEntity();
List<UserEntity> userList = userEntity.createList();
Optional<UserEntity> max = userList.stream().max(Comparator.comparingDouble(UserEntity::getScore));
System.out.println("对象集合中分数最高的人:"+max.get().getName());

 对象集合中分数最高的人:姬如雪

 3.2.5、计算集合中大于6的元素的个数。

List<Integer> integerList = Arrays.asList(5, 2, 9, 4, 16, 6);
long count = integerList.stream().filter(x -> x > 3).count();
System.out.println("list中大于3的元素个数:" + count);

list中大于3的元素个数:5 

3.3、收集(collect)  归集(toList/toSet/toMap)

collect收集,可以说是内容最繁多、功能最丰富的部分了。可以理解为把一个流收集起来,最终可以是收集成一个值也可以收集成一个新的集合。

3.3.1、toList

List<Integer> list = Arrays.asList(1, 6, 3, 4, 6, 8, 9, 6, 5);
List<Integer> listNew = 
     list.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());
   System.out.println("初始化集合:" + list);
   System.out.println("过滤生成新的集合:" + listNew);

初始化集合:[1, 6, 3, 4, 6, 8, 9, 6, 5]
过滤生成新的集合:[6, 4, 6, 8, 6]

3.3.2、toSet

List<Integer> list = Arrays.asList(1, 6, 3, 4, 6, 8, 9, 6, 5);
Set<Integer> set = 
        list.stream().filter(x -> x % 2 == 0).collect(Collectors.toSet());
System.out.println("初始化集合:" + list);
System.out.println("过滤生成Set集合:" + set);

 初始化集合:[1, 6, 3, 4, 6, 8, 9, 6, 5]
过滤生成Set集合:[4, 6, 8]

3.3.3、toMap

  UserEntity userEntity = new UserEntity();
  List<UserEntity> userList = userEntity.createList();
  Map<String, UserEntity> userMap = 、userList.stream().filter(p -> p.getScore() > 95)
                .collect(Collectors.toMap(UserEntity::getName, p -> p));
  System.out.println(userMap);

{女帝=com.enter.entity.UserEntity@4f3f5b24, 姬如雪=com.enter.entity.UserEntity@15aeb7ab}

 3.4、映射(map/flatMap)

map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。

 3.4.1、map

        英文字符串数组的元素全部改为小写。数组每个元素乘上3。

        String[] strArr = { "CODE", "Wang"};
        List<String> strList = Arrays.stream(strArr).map(String::toLowerCase).collect(Collectors.toList());
        System.out.println("元素小写:"+strList);

        List<Integer> intList = Arrays.asList(1, 3, 5, 7, 9, 11);
        List<Integer> intListNew = intList.stream().map(x -> x * 3).collect(Collectors.toList());
        System.out.println("每个元素*3:"+intListNew);

 元素小写:[code, wang]
每个元素*3:[3, 9, 15, 21, 27, 33]

3.4.2、 flatMap

        将两个字符数组合并成一个新的字符数组。

List<String> list = Arrays.asList("c-o-d-e", "w-a-n-g");
        List<String> listNew = list.stream().flatMap(s -> {
            // 将每个元素转换成一个stream
            String[] split = s.split("-");
            Stream<String> s2 = Arrays.stream(split);
            return s2;
        }).collect(Collectors.toList());

        System.out.println("处理前的集合:" + list);
        System.out.println("处理后的集合:" + listNew);

处理前的集合:[c-o-d-e, w-a-n-g]
处理后的集合:[c, o, d, e, w, a, n, g]

3.5、归约(reduce / reducing) 

   3.5.1、归约(reduce)

        也称缩减,是把一个流缩减成一个值,能实现对集合求和、求乘积和求最值操作。 

List<Integer> list = Arrays.asList(1, 3, 2, 8, 11, 4);
        // 求和方式1
        Optional<Integer> sum = list.stream().reduce((x, y) -> x + y);
        // 求和方式2
        Optional<Integer> sum2 = list.stream().reduce(Integer::sum);
        // 求和方式3
        Integer sum3 = list.stream().reduce(0, Integer::sum);

        // 求乘积
        Optional<Integer> product = list.stream().reduce((x, y) -> x * y);

        // 求最大值方式1
        Optional<Integer> max = list.stream().reduce((x, y) -> x > y ? x : y);
        // 求最大值写法2
        Integer max2 = list.stream().reduce(1, Integer::max);

        System.out.println("list求和方式一:" + sum.get() + ",方式二:" + sum2.get() + ",方式三:" + sum3);
        System.out.println("list求积:" + product.get());
        System.out.println("list求最大值方式一:" + max.get() + ",求最大值方式二:" + max2);

list求和方式一:29,方式二:29,方式三:29
list求积:2112
list求最大值方式一:11,求最大值方式二:11

     3.5.2、归约(reducing) 

   Collectors类提供的reducing方法,相比于stream本身的reduce方法,增加了对自定义归约   的支持。 

 UserEntity userEntity = new UserEntity();
        List<UserEntity> userList = userEntity.createList();

        // 每个学员各科成绩减去5之后的成绩之合
        Double sum = userList.stream().collect(Collectors.reducing(0.0, UserEntity::getScore, (i, j) -> (i + j - 5)));
        System.out.println("员工减去国定值总和:" + sum);

        // stream的reduce
        Optional<Double> sum2 = userList.stream().map(UserEntity::getScore).reduce(Double::sum);
        System.out.println("所有成绩总和:" + sum2.get());

员工减去国定值总和:526.0
所有成绩总和:556.0

3.6、统计 

 Collectors提供了一系列用于数据统计的静态方法:

  1. 计数:count
  2. 平均值:averagingIntaveragingLongaveragingDouble
  3. 最值:maxByminBy
  4. 求和:summingIntsummingLongsummingDouble
  5. 统计以上所有:summarizingInt、summarizingLong、summarizingDouble

3.6.1、计数

        UserEntity userEntity = new UserEntity();
        List<UserEntity> userList = userEntity.createList();
        // 总数
        Long count = userList.stream().collect(Collectors.counting());
        System.out.println("List总数:" + count);

 List总数:6

 3.6.2、平均值

        UserEntity userEntity = new UserEntity();
        List<UserEntity> userList = userEntity.createList();
        // 平均成绩
        Double average = userList.stream().collect(Collectors.averagingDouble(UserEntity::getScore));
        System.out.println("学生平均成绩:" + average);

学生平均成绩:92.66666666666667

3.6.3、最值

        UserEntity userEntity = new UserEntity();
        List<UserEntity> userList = userEntity.createList();
        // 最高成绩
        Optional<Double> max = userList.stream().map(UserEntity::getScore).collect(Collectors.maxBy(Double::compare));
        System.out.println("最高成绩:" + max.get());

最高成绩:96.5 

3.6.4、求和

        UserEntity userEntity = new UserEntity();
        List<UserEntity> userList = userEntity.createList();
        // 总和
        Double sum = userList.stream().collect(Collectors.summingDouble(UserEntity::getScore));
        System.out.println("成绩总和:" + sum);

成绩总和:556.0 

3.6.5、统计以上所有

        UserEntity userEntity = new UserEntity();
        List<UserEntity> userList = userEntity.createList();
        // 一次性统计所有信息
        DoubleSummaryStatistics collect = userList.stream().collect(Collectors.summarizingDouble(UserEntity::getScore));
        System.out.println("成绩所有统计:" + collect);

 成绩所有统计:DoubleSummaryStatistics{count=6, sum=556.000000, min=85.500000, average=92.666667, max=96.500000}

 3.7、分组(partitioningBy/groupingBy)

分区:将stream按条件分为两个Map,比如员工按成绩是否高于95分为两部分。
分组:将集合分为多个Map,比如员工按性别分组。有单级分组和多级分组。

        UserEntity userEntity = new UserEntity();
        List<UserEntity> userList = userEntity.createList();
        // 按成绩是否高于95分组
        Map<Boolean, List<UserEntity>> part = userList.stream().collect(Collectors.partitioningBy(x -> x.getScore() > 95));
        // 按性别分组
        Map<String, List<UserEntity>> group = userList.stream().collect(Collectors.groupingBy(UserEntity::getSex));
        // 先按性别分组,再按学科分组
        Map<String, Map<String, List<UserEntity>>> group2 =
                userList.stream().collect(Collectors.groupingBy(UserEntity::getSex, Collectors.groupingBy(UserEntity::getSubject)));
        System.out.println("按成绩是否大于95分组情况:" + part);
        System.out.println("按性别分组情况:" + group);
        System.out.println("按性别、学科:" + group2);

 按成绩是否大于95分组情况:{false=[com.enter.entity.UserEntity@1d81eb93, com.enter.entity.UserEntity@7291c18f, com.enter.entity.UserEntity@34a245ab, com.enter.entity.UserEntity@7cc355be], true=[com.enter.entity.UserEntity@6e8cf4c6, com.enter.entity.UserEntity@12edcd21]}


按性别分组情况:{女=[com.enter.entity.UserEntity@6e8cf4c6, com.enter.entity.UserEntity@12edcd21, com.enter.entity.UserEntity@7291c18f, com.enter.entity.UserEntity@34a245ab], 男=[com.enter.entity.UserEntity@1d81eb93, com.enter.entity.UserEntity@7cc355be]}


按性别、学科:{女={数学=[com.enter.entity.UserEntity@7291c18f, com.enter.entity.UserEntity@34a245ab], 语文=[com.enter.entity.UserEntity@6e8cf4c6, com.enter.entity.UserEntity@12edcd21]}, 男={数学=[com.enter.entity.UserEntity@7cc355be], 语文=[com.enter.entity.UserEntity@1d81eb93]}}

 3.8、接合(joining)

  joining可以将stream中的元素用特定的连接符(没有的话,则直接连接)连接成一个字符串。

        UserEntity userEntity = new UserEntity();
        List<UserEntity> userList = userEntity.createList();
        String names = userList.stream().map(p -> p.getName()).collect(Collectors.joining(","));
        System.out.println("所有学员的姓名:" + names);
       

 所有学员的姓名:姬如雪,女帝,李星云,姬如雪,女帝,李星云

3.9、排序(sorted) 

       sorted,中间操作。有两种排序: 

                sorted():自然排序,流中元素需实现Comparable接口
                sorted(Comparator com):Comparator排序器自定义排序

        UserEntity userEntity = new UserEntity();
        List<UserEntity> userList = userEntity.createList();

        // 按成绩升序排序(自然排序)
        List<String> newList = userList.stream().sorted(Comparator.comparing(UserEntity::getScore)).map(UserEntity::getName)
                .collect(Collectors.toList());
        // 按成绩倒序排序
        List<String> newList2 = userList.stream().sorted(Comparator.comparing(UserEntity::getScore).reversed())
                .map(UserEntity::getName).collect(Collectors.toList());
        // 先按成绩再按年龄升序排序
        List<String> newList3 = userList.stream()
                .sorted(Comparator.comparing(UserEntity::getScore).thenComparing(UserEntity::getAge)).map(UserEntity::getName)
                .collect(Collectors.toList());
        // 先按成绩再按年龄自定义排序(降序)
        List<String> newList4 = userList.stream().sorted((p1, p2) -> {
            if (p1.getScore() == p2.getScore()) {
                return p2.getAge() - p1.getAge();
            } else {
                return (int) (p2.getScore() - p1.getScore());
            }
        }).map(UserEntity::getName).collect(Collectors.toList());

        System.out.println("按成绩升序排序:" + newList);
        System.out.println("按成绩降序排序:" + newList2);
        System.out.println("先按成绩再按年龄升序排序:" + newList3);
        System.out.println("先按成绩再按年龄自定义降序排序:" + newList4);

按成绩升序排序:[李星云, 李星云, 姬如雪, 女帝, 女帝, 姬如雪]
按成绩降序排序:[姬如雪, 女帝, 女帝, 姬如雪, 李星云, 李星云]
先按成绩再按年龄升序排序:[李星云, 李星云, 姬如雪, 女帝, 女帝, 姬如雪]
先按成绩再按年龄自定义降序排序:[姬如雪, 女帝, 女帝, 姬如雪, 李星云, 李星云]

4、 合并、去重、限制、跳过

      String[] arr1 = {"c", "o", "d", "e"};
        String[] arr2 = {"w", "a", "n", "g", "e"};

        Stream<String> stream1 = Stream.of(arr1);
        Stream<String> stream2 = Stream.of(arr2);
        // 使用concat:合并两个流 distinct:去重
        List<String> newList = Stream.concat(stream1, stream2).distinct().collect(Collectors.toList());
        // 使用limit:限制从流中获得前n个数据
        List<Integer> limitList  = Stream.iterate(1, x -> x + 2).limit(10).collect(Collectors.toList());
        // 使用skip:跳过前n个数据
        List<Integer> skipList = Stream.iterate(1, x -> x + 2).skip(1).limit(5).collect(Collectors.toList());

        System.out.println("流合并:" + newList);
        System.out.println("限制 :" + limitList);
        System.out.println("跳过 :" + skipList);

流合并:[c, o, d, e, w, a, n, g]
限制 :[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
跳过 :[3, 5, 7, 9, 11]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值