集合处理常用Stream流

集合处理常用Stream流

  • 1、Stream API介绍
  • 2、List集合常用Stream方法

stream流经常使用,但是遇到一些流操作时,会一下想不到用哪种,这里总结一下,方便自己或者读者查找

1、Stream API介绍

Stream API是Java 8引入的一项重要特性,它提供了一种新的处理集合数据的方式。Stream可以看作是一种高级的迭代器,它允许以声明式的方式对集合进行各种操作,如过滤、映射、排序、归约等。它可以简化集合处理的代码,并且在处理大数据集时具有性能优势。
个人理解:stream流就像一条源源不断的流水线或者管道,原材料从一端进入生产线,经过一系列的加工和处理,最终成品从另一端输出。在这个过程中,每个工人(方法)负责自己的任务,并将结果传递给下一个工人(方法),形成一个连续的操作链。直到遇到终止方法,才会生成最后的结果。

2、List集合常用Stream方法

1、stream(): 返回一个顺序流(Stream)。parallelStream(): 返回一个并行流(Stream)。

并行处理:Stream API提供了并行处理的能力,可以利用多线程来加速大数据集的处理。通过调用parallelStream()方法,可以将流转换为并行流,使得操作可以并行地执行。

List<String> list = Arrays.asList("apple", "banana", "cat");
Stream<String> stream = list.stream();
Stream<String> parallelStream = list.parallelStream();

2、filter(Predicate predicate): 过滤元素,保留符合条件的元素。传入是一个Predicate函数式接口,返回true:保留,false: 丢弃

List<String> list = Arrays.asList("apple", "banana", "cat");
Stream<String> filteredStream = list.stream().filter(s -> s.startsWith("a"));

3、distinct(): 去除重复的元素。

List<String> list = Arrays.asList("apple", "banana", "apple");
Stream<String> distinctStream = list.stream().distinct();

4、sorted(): 对元素进行排序,默认使用自然顺序。

List<Integer> list = Arrays.asList(3, 1, 2);
Stream<Integer> sortedStream = list.stream().sorted();

4.1 也可以自定义比较器,也就是参数中需要填写一个比较器 “sorted(Comparator<? super T> comparator)” 例如:

//字符串忽略大小写并排序
List<String> names = Arrays.asList("John", "Alice", "Bob", "Charlie");
List<String> sortedNames = names.stream().sorted((a, b) -> a.compareToIgnoreCase(b)).collect(Collectors.toList());

//对引用类型排序,通过其中的一个属性排序
class Person {
    private String name;
    private int age;

    // 省略构造函数和其他方法

    // Getter和Setter方法

    // ...
}
List<Person> persons = Arrays.asList(
        new Person("Alice", 25),
        new Person("Bob", 30),
        new Person("Charlie", 20)
);

List<Person> sortedPersons = persons.stream()
        .sorted(Comparator.comparingInt(Person::getAge))
        .collect(Collectors.toList());

5、limit(long maxSize): 限制流中元素的数量。

List<String> list = Arrays.asList("apple", "banana", "cat");
Stream<String> limitedStream = list.stream().limit(2);

6、forEach(Consumer action): 对每个元素执行给定的操作。就是遍历

List<String> list = Arrays.asList("apple", "banana", "cat");
list.stream().forEach(System.out::println);

7、map(Function<T, R> mapper): 将元素进行映射,得到一个新的流。这个不是转为一个map,该方法接受一个Function<T, R>函数接口作为参数,该函数接受一个输入类型为T的元素,并返回一个输出类型为R的结果。

List<String> list = Arrays.asList("apple", "banana", "cat");
Stream<Integer> lengthStream = list.stream().map(String::length);

7.1 map()方法允许我们在流中对每个元素进行自定义的转换操作,并生成一个新的流。通过传递适当的Function函数接口实现,我们可以实现各种转换操作,如类型转换、属性提取、计算转换等。例如:

class Person {
    private String name;
    // ...
}

List<Person> persons = Arrays.asList(
        new Person("Alice"),
        new Person("Bob"),
        new Person("Charlie")
);
//提取name,生成一个新的List<String>
List<String> names = persons.stream()
        .map(Person::getName)
        .collect(Collectors.toList());
//将一个person转换为一个student
 List<Student> students = persons.stream()
                .map(person -> {
                    String name = person.getName();
                    int age = person.getAge();
                    String school = getSchoolBasedOnAge(age); // 自定义的逻辑方法
                    return new Student(name, age, school);
                })
                .collect(Collectors.toList());
 private static String getSchoolBasedOnAge(int age) {
        if (age < 18) {
            return "High School";
        } else {
            return "University";
        }
    }

8、collect(Collector<? super T, A, R> collector): 将流中的元素收集到一个集合或其他可变结果容器中。最简单的就是返回一个新的List,上面方法都是

List<String> list = Arrays.asList("apple", "banana", "cat");
List<String> collectedList = list.stream().collect(Collectors.toList());

8.1、collect(Collector<? super T, A, R> collector) 是 Stream API 中的一个终端操作方法,用于将流中的元素收集到一个集合或其他可变结果容器中。该方法接受一个Collector对象作为参数,用于定义收集元素的规则。Collector对象可以通过Collectors工厂类的静态方法创建,也可以自定义实现。

Collector<? super T, A, R> 中的泛型参数表示以下内容:
T:表示流中的元素类型。? super T 表示任何 T 类型的超类型,这允许 Collector 处理 T 类型及其子类型的元素。
A:表示用于累积流元素的可变结果容器(accumulator)的类型。在收集过程中,Collector 将逐个元素累积到 A 类型的容器中。
R:表示收集操作的最终结果类型。Collector 最终将累积的结果转换为 R 类型,并返回结果。
在 Collector<? super T, A, R> 中,? super T 允许处理 T 类型及其子类型的元素。这种设计使得 Collector 更加通用,可以处理不同类型的元素,而不仅仅局限于 T 类型。累积结果容器的类型 A,以及收集操作的最终结果类型 R

例如:常用的list转map

public static void main(String[] args) {
        List<Person> persons = Arrays.asList(
                new Person("Alice", 25),
                new Person("Bob", 30),
                new Person("Charlie", 35)
        );

        Map<String, Integer> nameToAgeMap = persons.stream()
                .collect(Collectors.toMap(Person::getName, Person::getAge));

        System.out.println(nameToAgeMap);
    }

转为< id:实体 >

//在toMap()方法中,我们传递了三个参数:Person::getName用于提取姓名作为键,Function.identity()
//用于将Person对象本身作为值,以及一个合并函数 (existingValue, newValue) -> newValue 来处理
//重复的键。在合并函数中,我们选择使用新值作为合并后的值。
public static void main(String[] args) {
        List<Person> persons = Arrays.asList(
                new Person("Alice", 25),
                new Person("Bob", 30),
                new Person("Alice", 35)
        );

        Map<String, Person> nameToPersonMap = persons.stream()
                .collect(Collectors.toMap(Person::getName, Function.identity(), (existingValue, newValue) -> newValue));

        System.out.println(nameToPersonMap);
    }

8.2 使用collect()方法分组,以年龄分组

public static void main(String[] args) {
        List<Person> persons = Arrays.asList(
                new Person("Alice", 25),
                new Person("Bob", 30),
                new Person("Charlie", 35),
                new Person("Dave", 25)
        );

        Map<Integer, List<Person>> ageGroupMap = persons.stream()
                .collect(Collectors.groupingBy(Person::getAge));

        System.out.println(ageGroupMap);
    }

多层分组,根据城市和年龄进行多级分组。

public static void main(String[] args) {
        List<Person> persons = Arrays.asList(
                new Person("Alice", "New York", 25),
                new Person("Bob", "London", 30),
                new Person("Charlie", "New York", 35),
                new Person("Dave", "London", 25)
        );

        Map<String, Map<String, List<Person>>> cityToAgeGroupMap = persons.stream()
                .collect(Collectors.groupingBy(Person::getCity,
                        Collectors.groupingBy(person -> person.getAge() < 30 ? "Young" : "Old")));

        System.out.println(cityToAgeGroupMap);

得到了一个名为resultMap的嵌套的Map,其中外层的键是姓名,内层的键是年龄,值是对应的Person对象。

public static void main(String[] args) {
        List<Person> persons = Arrays.asList(
                new Person("Alice", 25),
                new Person("Bob", 30),
                new Person("Charlie", 35),
                new Person("Dave", 25)
        );

        Map<String, Map<Integer, Person>> resultMap = persons.stream()
                .collect(Collectors.groupingBy(
                        Person::getName,
                        Collectors.toMap(
                                Person::getAge,
                                person -> person
                        )
                ));

        System.out.println(resultMap);
    }

还可以做这些事情:

统计和汇总:
Collectors.counting(): 统计流中元素的数量。
Collectors.summingInt(toIntFunction): 对流中的元素进行整数求和。
Collectors.averagingInt(toIntFunction): 计算流中元素的平均值。
Collectors.summarizingInt(toIntFunction): 生成流中元素的汇总统计结果,包括数量、总和、平均值、最大值和最小值。

字符串拼接和连接:
Collectors.joining(): 将流中的元素按照指定的分隔符连接成一个字符串。
Collectors.joining(delimiter, prefix, suffix): 将流中的元素按照指定的分隔符、前缀和后缀连接成一个字符串。

9、allMatch(Predicate<? super T> predicate): 检查流中的所有元素是否都满足给定条件。返回boolean

List<Integer> list = Arrays.asList(2, 4, 6);
boolean allEven = list.stream().allMatch(n -> n % 2 == 0);

10、skip(long n): 跳过流中的前n个元素。这个可以用于列表分页
代码如下:跳过当前页前面的元素,然后再通过limit限制每页的大小
在这里插入图片描述
11、reduce(BinaryOperator accumulator): 根据给定的累加器函数对流中的元素进行归约操作。

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> sum = list.stream().reduce(0, (a, b) -> a + b);

找一个列表中年龄最大的Person

List<Person> people = Arrays.asList(
    new Person("John", 25),
    new Person("Alice", 30),
    new Person("Bob", 20)
);
Person oldestPerson = people.stream().reduce((p1, p2) -> p1.getAge() > p2.getAge() ? p1 : p2).orElse(null);

当然还可以做其他聚合和累积操作,具体在遇到聚合或者累加时,可以想到.reduce方法。

12、distinct(): 去除重复的元素。

List<String> list = Arrays.asList("apple", "banana", "apple");
Stream<String> distinctStream = list.stream().distinct();

13、flatMap(Function<? super T, ? extends Stream<? extends R>> mapper): 将流中的每个元素进行映射后扁平化成一个流。这个也是很好用的方法

List<List<Integer>> nestedList = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4));
List<Integer> flattenedList = nestedList.stream().flatMap(Collection::stream).collect(Collectors.toList());

13.1、flatMap() 方法在处理嵌套结构、处理多个集合或流之间的映射关系时非常有用。它可以将嵌套的集合或流展开为一个更简单的结构,方便后续的处理和操作。

List<List<List<String>>> nestedList = Arrays.asList(
    Arrays.asList(
        Arrays.asList("apple", "banana"),
        Arrays.asList("cherry", "date")
    ),
    Arrays.asList(
        Arrays.asList("grape", "kiwi"),
        Arrays.asList("lemon", "mango")
    )
);

List<String> flattenedList = nestedList.stream()
    .flatMap(List::stream)
    .flatMap(List::stream)
    .collect(Collectors.toList());

System.out.println(flattenedList); // 输出:[apple, banana, cherry, date, grape, kiwi, lemon, mango]

假设有一个 Person 类型,其中每个人可以有多个爱好(hobbies)。每个爱好又可以有多个标签(tags)。我们可以使用 flatMap() 方法来处理这种嵌套的引用类型结构。

public static void main(String[] args) {
        List<Person> people = Arrays.asList(
                new Person("John", Arrays.asList("Reading", "Painting")),
                new Person("Alice", Arrays.asList("Music", "Cooking", "Hiking")),
                new Person("Bob", Arrays.asList("Photography"))
        );

        List<String> allHobbies = people.stream()
                .flatMap(person -> person.getHobbies().stream())
                .collect(Collectors.toList());

        System.out.println(allHobbies);
    }

使用 flatMap() 方法,我们将 people 列表中每个人的爱好(List)流化,并将它们扁平化成一个单一的流。最后,我们将流收集为一个列表 allHobbies,其中包含所有人的爱好。

后续有更好用的再补充。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/35633.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue对于数组的数据监听变化和object是不一样的吗?

我们知道vue对于数组的数据监听变化和object是不一样的&#xff0c;因为我们常说的Object.defineProperty是对象上面的方法&#xff0c;所以对于array数组需要实现另外一套变化侦测机制。 今天我们就来研究下。 在哪里收集依赖 array数据设计了新的变化侦测机制&#xff0c;…

10个图像处理的Python库

在这篇文章中&#xff0c;我们将整理计算机视觉项目中常用的Python库&#xff0c;如果你想进入计算机视觉领域&#xff0c;可以先了解下本文介绍的库&#xff0c;这会对你的工作很有帮助。 1、PIL/Pillow Pillow是一个通用且用户友好的Python库&#xff0c;提供了丰富的函数集…

QT day1简单登录界面

widget.cpp文件代码&#xff1a; #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget) {qDebug()<<this->size();qDebug()<<this->frameSize();this->setFixedSize(50…

如何用Python搭建监控平台

监控和运维&#xff0c;是互联网工业链上非常重要的一环。监控的目的就是防患于未然。通过监控&#xff0c;我们能够及时了解到企业网络的运行状态。一旦出现安全隐患&#xff0c;你就可以及时预警&#xff0c;或者是以其他方式通知运维人员&#xff0c;让运维监控人员有时间处…

MATLAB 之 可视化图形用户界面设计

这里写目录标题 一、可视化图形用户界面设计1. 图形用户界面设计窗口1.1 图形用户界面设计模板1.2 图形用户界面设计窗口 2. 可视化图形用户界面设计工具1.1 对象属性检查器2.2 菜单编辑器2.3 工具栏编辑器2.4 对齐对象工具2.5 对象浏览器2.6 Tab 键顺序编辑器 3. 可视化图形用…

多元分类预测 | Matlab基于北方苍鹰优化深度置信网络(NGO-DBN)的分类预测,多输入模型,NGO-DBN分类预测

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元分类预测 | Matlab基于北方苍鹰优化深度置信网络(NGO-DBN)的分类预测,多输入模型,NGO-DBN分类预测 多特征输入单输出的二分类及多分类模型。程序内注释详细,直接替换数据就可以用。程序语言为matlab,程序可…

地下饮用水除硝酸盐技术、生活用水提质增效

项目名称 北京某地下水除硝酸盐项目&#xff0c;出水未检出 工艺选择 两处水源&#xff0c;运行方式为一用一备 工艺原理 树脂官能团耐受硫酸盐、氯离子的干扰&#xff0c;实现选择性吸附硝酸根 项目背景 近年来由于农业活动及排污物的影响&#xff0c;部分地表…

【STM32】STM32G系列使用CORDIC模块加速计算

1.前言 STM32G431系列产品内置了CORDIC运算单元&#xff0c;可以用来加速数学计算&#xff0c;如三角函数、取模、开方等。适合大量数据进行相同的运算操作。配合DMA可以大大节省CPU计算开销。 2.CubeMX配置 使用CORDIC模块无需配置参数&#xff0c;若采用DMA方式则只需配置…

多元分类预测 | Matlab基于灰狼优化深度置信网络(GWO-DBN)的分类预测,多特征输入模型,GWO-DBN分类预测

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元分类预测 | Matlab基于灰狼优化深度置信网络(GWO-DBN)的分类预测,多特征输入模型,GWO-DBN分类预测 多特征输入单输出的二分类及多分类模型。程序内注释详细,直接替换数据就可以用。程序语言为matlab,程序可…

如何提高OAK相机在树莓派和JETSON上的运行帧率?

编辑&#xff1a;OAK中国 首发&#xff1a;oakchina.cn 喜欢的话&#xff0c;请多多&#x1f44d;⭐️✍ 内容可能会不定期更新&#xff0c;官网内容都是最新的&#xff0c;请查看首发地址链接。 Hello&#xff0c;大家好&#xff0c;这里是OAK中国&#xff0c;我是助手君。 最…

【嵌入式Qt开发入门】如何使用Qt进行绘制实时图表——QChart 图表

要想使用 Qt Charts&#xff0c;我们的 Qt 版本得使用 Qt 5.7 之后的版本。其实 Qt Charts 并不是 Qt 5.7 才有的&#xff0c;是在 Qt 5.7 以前只有商业版本的 Qt 才有 Qt Charts。我们能免费下载的 Qt 版本都是社区&#xff08;开源&#xff09;版本。 Qt Charts 很方便的绘制…

密码学入门——DES与AES

文章目录 参考书目一、编码与异或1.1 编码1.2 异或 二、DES与三重DES三、AES 参考书目 图解密码技术&#xff0c;第三版 一、编码与异或 1.1 编码 计算机的操作对象并不是文字&#xff0c;而是由0和1排列而成的比特序列。无论是文字、图像、声音、视频还是程序&#xff0c;…

win系统删除oracle数据文件恢复---惜分飞

有客户联系我们,说win平台下的数据库,在由于空间紧张,在关闭数据库的情况下删除的两个数据文件,导致数据库无法正常访问很多业务表,需要对其进行恢复,查看alert日志发现大概操作,删除文件之后,启动数据库失败 Completed: alter database mount exclusive alter database open E…

【案例实战】SpringBoot整合Redis的GEO实现查找附近门店功能

像我们平常美团点外卖的时候&#xff0c;都会看到一个商家距离我们多少米。还有类似QQ附近的人&#xff0c;我们能看到附近的人距离我们有多少米。 那么这些业务是怎么做的呢&#xff1f;是如何实现 基于位置的附近服务系统呢。 在去了解基于位置的附近服务之前&#xff0c;我…

个人域名邮箱无法给gmail发邮件

问题描述 我注册了一个域名 mydomain.com, 并在此域名下创建了 mailbox&#xff0c;从该邮箱向外发送邮件和接收邮件会失败。 主要是一些配置工作没有做好。 接收邮件 当创建邮箱 xxxmydomain.com&#xff0c;尝试向该邮箱发送邮件时&#xff0c;邮件会被拒收&#xff0c;并…

在Linux中安装RabbitMQ

RabbitMQ下载网址 Socat下载网址 erlang下载网址 RabbitMQ安装包依赖于Erlang语言包的支持&#xff0c;所以需要先安装Erlang语言包&#xff0c;再安装RabbitMQ安装包 通过Xftp软件将这三个压缩包上传到linux中的opt目录下 ,双击即可 在安装之前先查询…

Css基础:盒子模型

1.盒子模型的构成&#xff1a; 边框 外边距 内边距 实际内容 2.table表格的单元格之间的线太粗需要border-collapse:collapse;合并一下边框宽度 3.内边距 padding 4.外边距 margin 块元素水平居中的做法&#xff0c;margin:0 auto; 行内元素和行内块元素 水平居中做…

【Jenkins】Jenkins构建后端流水线

目录 一、新建任务1、输入任务名称&#xff0c;选择构建项目类型&#xff08;这里我选择的是Maven项目&#xff09;&#xff0c;任务名称一般格式为&#xff1a;项目名称-前后端2、创建成功后的结果 二、配置流水线1、进入刚创建好的任务页面中&#xff0c;点击配置2、General配…

快速入门uniapp——从环境搭建到项目实践

&#x1f642;博主&#xff1a;小猫娃来啦 &#x1f642;文章核心&#xff1a;快速入门uniapp——从环境搭建到项目实践 文章目录 初步介绍UniApp开发环境搭建下载和安装UniApp开发工具创建新项目&#xff08;HBuilderX&#xff09;开发工具界面介绍 UniApp基础知识页面结构页面…

SQLite Expert Professional将ACCESS数据库文件导入到SQLITE

一、下载与安装 下载对应的位数的SQLite Expert&#xff1a;http://www.sqliteexpert.com/download.html &#xff0c;建议下载professional版本的&#xff0c;功能更加强大。 如果官网进不去可以到百度云下载&#xff1a;https://pan.baidu.com/s/17igndAqQ7SQ57LcjwS4WIQ …