别再使用循环的方式筛选元素了!开发常用的Stream流+Lambda表达式过滤元素了解过吗?10000字超详细解析

目录

1. Stream 流的简单展示

1.1 抛出问题

1.2 传统解决问题的编码方式

1.3 Stream 流的方式过滤元素

2. Stream 流的核心思想

3. Stream 流的使用

3.1 获取 stream 流

3.1.1 单列集合获取 stream 流

3.1.2 双列集合获取 stream 流

3.1.3 数组获取 stream 流

3.1.4 零散数据获取 stream 流 

3.2 处理加工 stream 流

3.2.1 stream 流常用的方法

3.2.2 filter 方法代码演示

3.2.3 limit 方法代码演示

3.2.4 skip 方法代码演示

3.2.5 distinct 方法代码演示

3.2.6 concat 方法代码演示

3.2.7 map 方法代码演示

3.3 stream 流终结方法

3.3.1 stream 终结流常用方法

3.3.2 toArray 方法解析

3.3.3 collect 方法解析


1. Stream 流的简单展示

1.1 抛出问题

现创建一个集合并添加元素,如下代码,完成以下两个需求

需求1:把所有以 "张" 开头的元素添加到一个新的集合,输出结果;

需求2:把所有以 "张" 开头且长度为3的元素添加到另一个新的集合,输出结果;

public class Test6 {public static void main(String[] args) {List list = new ArrayList();list.add("张阳光");list.add("张三");list.add("李四");list.add("赵六");list.add("张大炮");}
}
1.2 传统解决问题的编码方式

拿到这个题的时候,按照我们的惯性思维,大多数人应该都想着遍历数组,然后拿出数组中的每个元素做比对,满足要求就存放到另一个新的数组中去,这是大多数人的常见解决思路。

代码我已经写好了,如下所示,逻辑比较简单,就不做过多说明了

public class Test6 {public static void main(String[] args) {ArrayList<String> list = new ArrayList();list.add("张阳光");list.add("张三");list.add("李四");list.add("赵六");list.add("张大炮");// 需求1解决方案// 创建一个新数组 list2ArrayList<String> list2 = new ArrayList();// for 循环遍历 listfor (String name : list) {// 调用API startWithif (name.startsWith("张")){// 将满足条件的加入到新的数组list2.add(name);}}System.out.println(list2);// 需求2解决方案// 创建一个新数组 list3ArrayList<String> list3 = new ArrayList<>();// 遍历刚才的 list2 集合for (String name : list2) {// 判断长度是否为3if (name.length() == 3){// 满足条件则加入到 list3 中list3.add(name);}}System.out.println(list3);}
}

我运行一下上面的代码,就可以在控制台得到结果,是我们期望的输出结果

1.3 Stream 流的方式过滤元素

刚才的普遍解决方案想必大家都已经知道了,下面我来给大家展示一下使用 Stream 流如何做到上面同样的效果。

代码如下

通过使用 stream 流,调用它里面已经定义好的 filter 过滤器方法,通过链式编程的方式一行代码就可以搞定

public class Test6 {public static void main(String[] args) {ArrayList<String> list = new ArrayList();list.add("张阳光");list.add("张三");list.add("李四");list.add("赵六");list.add("张大炮");// 需求1解决方案// list.stream()获取 list 集合的 stream 流// filter 为过滤方法。参数列表中通过 Lambda 表达式书写过滤规则// 过滤完毕 forEach 循环打印list.stream().filter(name -> name.startsWith("张")).forEach(name -> System.out.println(name));System.out.println("--------------------------");// 需求2解决方案
// 这里两次 filter 过滤两次,如果还有过滤条件可以继续链式添加 filter ,无限套娃list.stream().filter(name -> name.startsWith("张")).filter(name -> name.length() == 3).forEach(name -> System.out.println(name));}
}

运行上述代码,仍然可以在控制台得到期望结果

2. Stream 流的核心思想

同学们可以把 stream 流看作是一个流水线,我们待处理的数据就是一个待加工的零件,这个零件(要处理的数据)就会经过流水线的加工(stream 流),成为一个合格的产品(最终得到我们想要的数据)。

每次 filter 过滤就好比是一次加工过滤,或许我们需要过滤一次,又或许需要过滤多次。

我们对于 stream 流的操作基本可以分为"中间方法" 和 "终结方法" 两种,中间方法就是我们要对 stream 流中的数据做的各种操作,上述的过滤只是其中最为常用的一种,终结方法就是对 stream 流中的数据已经处理完毕,需要做打印输出,此时就不能再调用其他的方法。

3. Stream 流的使用

使用 stream 流处理数据,一般可以分为三个重要步骤;

第一步:获取到 stream 流,并把数据放上去;

第二步:对数据做一系列中间方法做加工;

第三步:对数据使用终结方法做最后的出炉成品;

3.1 获取 stream 流

在 Java 在,不同的对象获取流的方式也是不相同的,下图列举了几种非常常用的对象获取 stream流的方式

3.1.1 单列集合获取 stream 流

单列集合获取 stream 非常简单,在 Collection 中已经为我们提供好了方法,直接通过 "." 的方式调用即可,上面的例子中也已经写过了,这里就不再作演示了,

3.1.2 双列集合获取 stream 流

双列集合,例如常用的 Map 虽然不能直接获取 stream 流,但是我们可以调用其他方法将双列集合转化成单列集合的方式间接获取 stream流,如下代码

// 创建单列集合Map<String,Integer> map = new HashMap();// 调用 keySet 方法得到所有的键集合,键集合为单列集合,再获取 stream流map.keySet().stream();// 调用 entrySet 获取到所有键值对对象的单列集合,再获取 stream流map.entrySet().stream();
3.1.3 数组获取 stream 流

数组我们又可以分为存放基本数据类型的数组和存放引用数据类型的数组,他们在获取 stream 流时可以通过工具类 Arrays 中的方法获取 stream 流,调用方法时会发生重载;

我给大家看一下

// 基本数据类型数组int[] arr = {1,2,3,4,5};// 引用数据类型数组String[] arr2 = {"abd","dec","qqq"};// 调用 Arrays 类中的 stream 方法获取 stream 流Arrays.stream(arr);Arrays.stream(arr2);

上面的连行代码看似一样,但他们只是方法名相同,实际在运行的时候会发生重载,如下图所示,可以看到,Arrays 类中有好几个stream 方法针对于不同的数据类型

3.1.4 零散数据获取 stream 流 

零散的数据也可以获取 stream 流,可以通过调用 Stream 类中的 of 方法,

大家可以看到,在调用的时候,方法的参数中显示的是可变参数,所以也就是说参数的底层其实还是一个数组;

如下所示,参数可以为 字符串,整型,浮点型,这些零散不统一的数据,但是,这种方式几乎在开发中根本不会用,我们不会吧数据类型不一致的数据放在一起,所以自己敲代码的时候玩玩就可以了,这种 获取 stream 流的方式了解即可,主要记住前面三种方式,单双列数组和集合获取 stream 流的方式是重点。

Stream.of("1",2,3.4).forEach(s -> System.out.println(s));
3.2 处理加工 stream 流
3.2.1 stream 流常用的方法

stream 流对数据进行加工有以下常用的六个方法,而最最最为常用的就是 filter 过滤,实际开发过程中,我们通常会将数据存放在集合中,然后给予一些业务场景,就需要对集合进行过滤,就需要使用到 filter 过滤。

3.2.2 filter 方法代码演示

filter 方法我们在上面已经演示过了,所以这里就不再重复啰嗦了。

3.2.3 limit 方法代码演示

limit 表示获取前几个元素,方法参数类型为 Long,代码如下所示

public class Test6 {public static void main(String[] args) {ArrayList<String> list = new ArrayList();list.add("张阳光");list.add("张三");list.add("李四");list.add("赵六");list.add("张大炮");list.stream().limit(2).forEach(s -> System.out.println(s));}
}

运行,我们就可以在控制台得到,前两个元素,也就是 "张阳光","张三",如下图所示

3.2.4 skip 方法代码演示

skip 方法,表示跳过几个元素,方法参数类型为 Long,代码如下所示

public class Test6 {public static void main(String[] args) {ArrayList<String> list = new ArrayList();list.add("张阳光");list.add("张三");list.add("李四");list.add("赵六");list.add("张大炮");list.stream().skip(2).forEach(s -> System.out.println(s));}
}

运行,跳过前两个元素,我们就可以在控制台得到后三个元素,也就是 "李四","赵六","张大炮",如下图所示

3.2.5 distinct 方法代码演示

distinct 方法,去重,方法没有参数,和数据库中的去充实同样的道理,这里它底层去重是依据 equals 和 hashCode 方法,所以如果集合中添加的是自定义类型数据,请务必在类中重写 equals 和 hashCode 方法;

演示代码如下,我多添加几个相同的元素,打印输出

public class Test6 {public static void main(String[] args) {ArrayList<String> list = new ArrayList();list.add("张阳光");list.add("张阳光");list.add("张阳光");list.add("张三");list.add("李四");list.add("赵六");list.add("张大炮");list.add("张大炮");list.add("张大炮");list.stream().distinct().forEach(s -> System.out.println(s));}
}

运行,去掉相同的元素,我们预期在控制台得到五个元素,如下图所示

3.2.6 concat 方法代码演示

concat 合并两个流的方法,我调用此方法的时候,建议两个要合并的流存放相同类型的数据,如果存放的不相同,那么合并后的流存放的类型就两个流数据类型的父类,可能会导致原来自己独有的方法无法被调用,这一点要注意。

演示代码如下

我们综合前面的方法一并使用

public class Test6 {public static void main(String[] args) {ArrayList<String> list = new ArrayList();list.add("张阳光");list.add("张阳光");list.add("张三");list.add("李四");list.add("赵六");list.add("张大炮");list.add("张大炮");list.add("张大炮");// list.stream().distinct().limit(2) 先去重然后取前两个数据// list.stream().distinct().skip(2) 先去重跳过前两个数据// 合并后的两个流应该是完整的5个不重复数据Stream.concat(list.stream().distinct().limit(2),list.stream().distinct().skip(2)).forEach(s -> System.out.println(s));}
}

运行上述代码,期望值应该是完整的5个不重复的数据,如下图

3.2.7 map 方法代码演示

我们先来看一下 map 方法的参数,参数为 Function。

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

我们点击 Function 查看一下,它是一个函数式接口,那么它就可以简化成 Lambda 表达式的写法,接口中有一个 apply 方法,

map 方法可以用来转换流中数据的类型,我将之前集合中的元素内容修改一下,在每个元素的后面加上 "-年龄" ,

ArrayList<String> list = new ArrayList();list.add("张阳光-21");list.add("张三-22");list.add("李四-20");list.add("赵六-19");list.add("张大炮-18");

 现在我提出问题:要将他们的年龄从集合中取出来并转化成 Integer 类型输出,该怎么做?

(1)匿名内部类的写法

因为直接采用 Lambda 表达式的写法部分同学可能会不太能看懂,我先从匿名内部类的方式开始写,如下图,在参数中采用匿名内部类的形式书写,第一个泛型 String 是流中原本存放的数据类型,第二个泛型则是想要转为成的参数类型,这里应写为 Integer 我还没有改各位同学知道即可,



然后我们就可以再重写方法中编写具体逻辑了,如下代码

public class Test6 {public static void main(String[] args) {ArrayList<String> list = new ArrayList();list.add("张阳光-21");list.add("张三-22");list.add("李四-20");list.add("赵六-19");list.add("张大炮-18");/*** 匿名内部类书写方法*/list.stream().map(new Function<String, Object>() {@Overridepublic Object apply(String s) {// 调用 split 切割方法,从"-"字符串切割成两半,并定义 String 字符串数组接收String[] arr = s.split("-");// 切割成 "姓名" "年龄" 两部分,我们需要年龄String ageString = arr[1];// 转换为 Integer 类型Integer age = Integer.parseInt(ageString);// 将年龄做返回return age;}}).forEach(s2 -> System.out.println(s2));}
}

运行代码,在控制台就可以得到5个年龄数据,如下

(2)Lambda 表达式的方式书写

现在我们再来采用 Lambda 表达式的书写方法优化上述逻辑代码,上面的匿名内部类代码我并没有删除,各位同学可以对比观看,

如下,采用 Lambda 表达式,一行代码就可以搞定,完全不需要想匿名内部类那么复杂

public class Test6 {public static void main(String[] args) {ArrayList<String> list = new ArrayList();list.add("张阳光-21");list.add("张三-22");list.add("李四-20");list.add("赵六-19");list.add("张大炮-18");/*** 匿名内部类书写方法*/list.stream().map(new Function<String, Object>() {@Overridepublic Object apply(String s) {// 调用 split 切割方法,从"-"字符串切割成两半,并定义 String 字符串数组接收String[] arr = s.split("-");// 切割成 "姓名" "年龄" 两部分,我们需要年龄String ageString = arr[1];// 转换为 Integer 类型Integer age = Integer.parseInt(ageString);// 将年龄做返回return age;}}).forEach(s2 -> System.out.println(s2));System.out.println("----------------");/*** Lambda 表达式的书写方式* s.split("-")         分割字符串* s.split("-")[1]      获取年龄字符串* Integer.parseInt(s.split("-")[1]) 将字符串转化为 Integer 类型*/list.stream().map(s -> Integer.parseInt(s.split("-")[1])).forEach(age -> System.out.println(age));}
}

运行上述代码,得出结果,Lambda 表达式同样可以得到相同的效果。

3.3 stream 流终结方法
3.3.1 stream 终结流常用方法

经过了 stream 流的加工操作,我们就得到我符合我们条件的数据,然后我们就可以对数据进行最后的封装,有常用的四种方式,如下图所示

这里的话 forEach方法和 count 方法就不展示了,比较简单,重点来说一下 toArray 方法和 collect 方法

3.3.2 toArray 方法解析

toArray 方法一共有两个,一个空参方法,一个带参方法;

(1)toArray 空参方法

public static void main(String[] args) {ArrayList<String> list = new ArrayList();list.add("张阳光-21");list.add("张三-22");list.add("李四-20");list.add("赵六-19");list.add("张大炮-18");// toArray 空参方法,方法返回值是一个确定的 Object 数组Object[] objects = list.stream().toArray();// 直接打印输出的是 objects 的内存地址System.out.println(objects);// 调用 Arrays 类中的 toString 方法System.out.println(Arrays.toString(objects));}

运行得出结果

(2)toArray 带参方法

toArray 无参方法的返回值只能是 Object 类型的数组,当我们业务中想要的不是 Object 类型数组时,就可以使用带参 toArray 方法自定义返回的数组类型。

 如下为 toArray 方法的源码,方法的参数为 IntFunction

<A> A[] toArray(IntFunction<A[]> generator);

而它是一个函数式接口,所以可以采用匿名内部类或 Lambda 表达式的形式传入参数

采用匿名内部类的写法代码如下

public static void main(String[] args) {ArrayList<String> list = new ArrayList();list.add("张阳光-21");list.add("张三-22");list.add("李四-20");list.add("赵六-19");list.add("张大炮-18");// IntFunction 的泛型指具体类型的数组// apply 方法的参数指数组的长度,即流中元素的个数// 整个方法的目的就是返回一个指定聚类数据类型的且长度为流中数据元素个数的数组String[] strings = list.stream().toArray(new IntFunction<String[]>() {@Overridepublic String[] apply(int value) {return new String[value];}});System.out.println(Arrays.toString(strings));}

优化匿名内部类采用 Lambda 表达式代码如下,两行代码搞定

// Lambda 表达式的写法String[] strArr = list.stream().toArray(value -> new String[value]);System.out.println(Arrays.toString(strArr));

运行结果如下,两种方式都能得到期望的结果

3.3.3 collect 方法解析

开发时通常会把数据存放到List,Set,Map集合中。针对于三种不同的集合,自然需要对应不同的方法。

(1)针对于 List 集合

直接调用 collectors.toList 即可

public static void main(String[] args) {ArrayList<String> list = new ArrayList();list.add("张阳光-21");list.add("张三-22");list.add("李四-20");list.add("赵六-19");list.add("张大炮-18");// 过滤所有不为 "张" 开头的元素List<String> collect = list.stream().filter(name -> name.startsWith("张")).collect(Collectors.toList());System.out.println(collect);}

(2)针对于 Set 集合

直接调用 collectors.toSet 即可

// 过滤所有不为 "张" 开头的元素,存放到 Set 中Set<String> set = list.stream().filter(name -> name.startsWith("张")).collect(Collectors.toSet());System.out.println(set);

toList 方法和 toSet 方法有什么区别?

这两个方法的区别就和 List,Set 两个集合本身的区别差不多,toList 方法返回的集合有序可重复,而 toSet 方法返回的集合无需不可重复,一个例子即可验证

我们在上面的集合中添加一个重复的数据,分别调用两个方法,看运行结果

(3)针对于 Map 集合

调用 toMap 方法即可,但不同于 toList,toSet 的是,Map 是双列集合,K和V,所以我们需要确定键和值的数据类型。

对上面的题目做改变,现在我们把 List 集合中的元素拆开,让名字作为 Key,年龄作为 Value 存放到 Map 集合中,该怎么做?

public static void main(String[] args) {ArrayList<String> list = new ArrayList();list.add("张阳光-21");list.add("张三-22");list.add("李四-20");list.add("赵六-19");list.add("张大炮-18");
// k.split("-")[0] 分割字符串并获取0索引处的数据类型作为 Key 的泛型
// Integer.parseInt(v.split("-")[1]) 分割字符串取1索引处的字符串再转化为 Integer 作为value的泛型Map<String, Integer> collect = list.stream().collect(Collectors.toMap(k -> k.split("-")[0], v -> Integer.parseInt(v.split("-")[1])));}

这里有一个点需要注意,当我们要把数据存放到 Map 集合中的时候,键是不能重复的,否则代码会报错,我在上面的代码中再添加一个("张三-22"),运行如下

因为在 Map 中,不允许有重复的 key ,所以如果想要存放到 Map 集合中的时候,请先使用 filter 过滤器过滤掉相同的 key 元素。 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

低功耗蓝牙(BLE)开发——Qt

背景知识 低功耗蓝牙比经典蓝牙复杂些&#xff0c;需要了解一些协议的基础知识。 此部分参考博客GATT Profile 简介-CSDN博客 GATT详细介绍-CSDN博客 Introduction | Introduction to Bluetooth Low Energy | Adafruit Learning System 蓝牙 (四) GATT profile-CSDN博客 关…

Centos中利用自带的定时器Crontab_实现mysql数据库自动备份_linux中mysql自动备份脚本---Linux运维工作笔记056

这个经常需要,怕出问题因而需要经常备份数据库,可以利用centos自带的定时器,配合脚本实现自动备份. 1.首先查看一下,这个crontab服务有没有打开: 执行:ntsysv 可以看到已经开机自启动了. 注意这个操作界面,用鼠标不行,需要用,tab按键,直接tab到确定,或取消,然后按回车回到命…

CSS 之 table 表格布局

一、简介 ​ 除了使用HTML的<table>元素外&#xff0c;我们还可以通过display: table/inline-table; 设置元素内部的布局类型为表格布局。并结合table-cell、table-row等相关CSS属性值可以实现HTML中<table>系列元素的效果&#xff0c;具有表头、表尾、行、单元格…

Docker-compos

Docker-compose 简介 Docker-Compose项目是基于Python开发的Docker官方开源项目&#xff0c;负责实现对Docker容器集群的快速编排。 Docker-Compose将所管理的容器分为三层&#xff0c;分别是 工程&#xff08;project&#xff09;&#xff0c;服务&#xff08;service&#…

HSRP热备份路由器协议的解析和配置

HSRP的解析 个人简介 HSRP hot standby router protocol 热备份路由协议&#xff08;思科私有协议&#xff09; HSRP v1 version 1 HSRP v2 version 2 虚拟一个HSRP虚拟IP地址 192.168.1.1 开启HSRP的抢占功能 通过其他参数 人为调整谁是主 谁是从 &#xff01; 查…

记录一次线上fullgc问题排查过程

某天&#xff0c;接到测试部门反馈说线上项目突然很快&#xff0c;由于当前版本代码和上一版本相比就多了一个刚上线了一个5分钟1次的跑批任务&#xff0c;先关闭次任务后观察是否卡顿&#xff0c;并检查堆内存是否使用完造成频繁gc 1.通过jmap命令查看堆内存中的对象 2.生成当…

许战海战略文库|无增长则衰亡:中小型制造企业增长困境

竞争环境不是匀速变化&#xff0c;而是加速变化。企业的衰退与进化、兴衰更迭在不断发生&#xff0c;这成为一种不可避免的现实。事实上&#xff0c;在产业链竞争中增长困境不分企业大小&#xff0c;而是一种普遍存在的问题&#xff0c;许多收入在1亿至10亿美元间的制造企业也同…

PlantUML 绘图

官网 https://plantuml.com/zh/ 示例 绘制时序图 USB 枚举过程 PlantUML 源码 startuml host <-- device : device insert host note right : step 1 host -> device : get speed, reset, speed check note right : step 2 host -> device …

Premiere Elements 2024(PR简化版)直装版

Adobe Premiere Elements 2024 是一款由Adobe Systems推出的视频编辑软件&#xff0c;它结合了易用性和专业级的功能&#xff0c;帮助用户对视频进行剪辑、特效、色彩校正等处理。 主要功能和特点&#xff1a; 导入和组织视频&#xff1a;Premiere Elements 2024允许用户快速导…

ESP8266 WiFi物联网智能插座—下位机软件实现

目录 1、软件架构 2、开发环境 3、软件功能 4、程序设计 4.1、初始化 4.2、主循环状态机 4.3、初始化模式 4.4、配置模式 4.5、运行模式 4.6、重启模式 4.7、升级模式 5、程序功能特点 5.1、日志管理 5.2、数据缓存队列 本篇博文开始讲解下位机插座节点的MCU软件…

虚拟机软件Parallels Desktop 19 mac功能介绍

Parallels Desktop 19 mac是一款虚拟机软件&#xff0c;它允许用户在Mac电脑上同时运行Windows、Linux和其他操作系统。Parallels Desktop提供了直观易用的界面&#xff0c;使用户可以轻松创建、配置和管理虚拟机。 PD19虚拟机软件具有快速启动和关闭虚拟机的能力&#xff0c;让…

Kelper.js 笔记 python交互

1 加载Kepler 地图 KeplerGl() 1.1 主要参数 height 可选 默认值&#xff1a;400 地图显示的高度 data 数据集 字典&#xff0c;键是数据集的名称 config地图配置字典 1.2 举例 from keplergl import KeplerGlmap_KeplerGl() map_ 默认的位置 1.3 添加自己的图 1.3.1 读…

ElementPlus Switch 开关基础使用

昨天开发用到开关组件 后台返回字段是 can_write 默认是0 or 1 但是Switch 组件绑定的默认值默认是 true or false 直接绑定会导致默认是关闭状态 在页面一加载 值发生变化时 会自己调用 查了文档 需要使用 active-value 和 inactive-value 来指定绑定的数据类型 …

23种经典设计模式:单例模式篇(C++)

前言&#xff1a; 博主将从此篇单例模式开始逐一分享23种经典设计模式&#xff0c;并结合C为大家展示实际应用。内容将持续更新&#xff0c;希望大家持续关注与支持。 什么是单例模式&#xff1f; 单例模式是设计模式的一种&#xff08;属于创建型模式 (Creational Pa…

网页游戏的开发流程

网页游戏的开发流程可以根据项目的规模和复杂性而有所不同&#xff0c;但通常包括以下一般步骤&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.需求分析&#xff1a; 确定游戏的概念、目标受众和核…

手写 分页

子组件&#xff1a;TimePage.vue 效果图 <template><div class"click-scroll-X"><!-- 上 --><!-- eslint-disable-next-line --><span class"left_btn" :disabled"pageNo 1" click"leftSlide"><&…

PanoFlow:学习360°用于周围时间理解的光流

1.摘要&#xff1a; 光流估计是自动驾驶和机器人系统中的一项基本任务&#xff0c;它能够在时间上解释交通场景。自动驾驶汽车显然受益于360提供的超宽视野&#xff08;FoV&#xff09;◦ 全景传感器。 然而&#xff0c;由于全景相机独特的成像过程&#xff0c;为针孔图像设计…

NSIC2050JBT3G 车规级120V 50mA ±15% 用于LED照明的线性恒流调节器(CCR) 增强汽车安全

随着汽车行业的巨大变革&#xff0c;高品质的汽车氛围灯效、仪表盘等LED指示灯效已成为汽车内饰设计中不可或缺的元素。深力科安森美LED驱动芯片系列赋能智能座舱灯效充满艺术感和科技感——NSIC2050JBT3G LED驱动芯片&#xff0c;实现对每路LED亮度和颜色进行细腻控制&#xf…

SLAM从入门到精通(launch文件学习)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 大家应该还记得我们在一开始学习ros的时候&#xff0c;如果需要启动一个节点的话&#xff0c;需要首先打开roscore&#xff0c;接着用rosrun打开对…

shiro550复现环境搭建

前言 Shiro反序列化漏洞指的是Apache Shiro安全框架中的一个潜在漏洞&#xff0c;该漏洞可能导致攻击者能够通过精心构造的恶意序列化对象来执行任意代码或进行拒绝服务&#xff08;DoS&#xff09;攻击。 这种漏洞的根源是在Shiro的RememberMe功能中&#xff0c;当用户选择“…