Stream 管道流

news2024/11/25 4:35:43

文章目录

  • 前言
  • Stream Api
    • 1、流的创建
    • 2、中间操作
      • 2.1、有状态
        • ① distinct
        • ② sorted
        • ③ limit
        • ④ skip
        • ⑤ concat
      • 2.2、无状态
        • ① filter
        • ② map
        • ③ flatMap
        • ④ peek
        • ⑤ mapToInt、mapToLong、mapToDouble、flatMapToDouble、flatMapToInt、flatMapToLong
        • ⑥ unordered
    • 3、终结操作
      • 3.1、短路操作
        • ① anyMatch
        • ② allMatch
        • ③ noneMatch
        • ④ findFirst
        • ⑤ findAny
      • 3.2、非短路操作
        • ① forEach
        • ② forEachOrdered
        • ③ toArray
        • ④ reduce
        • ⑤ collect
        • ⑥ max
        • ⑦ min
        • ⑧ count

前言

在 java8 中添加了一个新的抽象,称之为 Stream,可以让程序员以一种声明式的方式处理数据,Stream流的处理方式,可以把要处理的元素看成一种流,流在管道中传输,并且在管道的节点上进行处理。

Stream 的操作可以分为两大类:中间操作、终结操作

中间操作可分为:

  • 无状态(Stateless)操作:指元素的处理不受之前元素的影响。
  • 有状态(Stateful)操作:指该操作只有拿到所有元素之后才能继续下去。

终结操作可分为:

  • 短路(Short-circuiting)操作:指遇到某些符合条件的元素就可以得到最终结果。
  • 非短路(Unshort-circuiting)操作:指必须处理完所有元素才能得到最终结果。

在这里插入图片描述

Stream Api

1、流的创建

  1. 通过 java.util.Collection.stream() 方法用集合创建流
List<String> list = Arrays.asList("hello", "world", "stream");
// 创建顺序流
Stream<String> stream = list.stream();
// 创建并行流
Stream<String> parallelStream = list.parallelStream();
  1. 使用 java.util.Arrays.stream(T[] array) 方法用数组创建流
String[] array = {"h", "e", "l", "l", "o"};
Stream<String> arrayStream = Arrays.stream(array);
  1. Stream的静态方法:of()、iterate()、generate()
// 这个方法不但支持将数组转成 Stream,也支持传入多个参数,将参数最终转成 Stream,其实 Stream.of() 也是调用的 Arrays.stream() 方法来实现的。
Integer[] array = new Integer[] {1, 2, 3};
Stream stream1 = Stream.of(array);
Stream<Integer> stream2 = Stream.of(1, 2, 3, 4, 5, 6);

// Stream 接口有两个用来创建无限 Stream 的静态方法。generate() 方法接受一个参数函数,可以使用类似如下代码来创建一个你需要的 Stream。
Stream<Double> stream3 = Stream.generate(Math::random).limit(3);

// Stream 接口的另一用来创建无限 Stream 的静态方法就是 iterate() 方法。iterate() 方法也是接受一个参数函数,可以用类似如下代码来创建一个你需要的 Stream。
Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2).limit(3);

串行流和并行流区分

流有串行和并行两种,串行流上的操作是在一个线程中依次完成,而并行流则是在多个线程上同时执行。并行与串行的流可以相互切换:通过 stream.sequential() 返回串行的流,通过 stream.parallel() 返回并行的流。相比较串行的流,并行的流可以很大程度上提高程序的执行效率。

在这里插入图片描述

2、中间操作

2.1、有状态

① distinct

  • distinct:去除重复元素。
    在这里插入图片描述
    样例:
Stream<String> stream = Stream.of("1", "2", "2", "1", "7", "9");
stream.distinct().forEach(System.out::println);// 1 2 7 9

那么如果需要对自定义的对象进行过滤,则需要重写对象的equals方法,另外有一个细节可以看到,去重之后还是按照原流中的排序顺序输出的,所以是有序的。

② sorted

  • sorted:自然排序,流中元素需实现 Comparable 接口。

该接口有两种形式:无参和有参数

Stream<T> sorted();
 
Stream<T> sorted(Comparator<? super T> comparator);

那区别其实就在于:传入比较器的参数,可以自定义这个比较器,即自定义比较规则。

Stream<String> stream = Stream.of("1", "2", "2", "1", "7", "9");
stream.sorted().forEach(System.out::println);// 1 1 2 2 7 9

③ limit

  • limit:获取 n 个元素。
    在这里插入图片描述
    样例:
Stream<String> stream = Stream.of("1", "2", "2", "1", "7", "9");
stream.limit(3).forEach(System.out::println);// 1 2 2

④ skip

  • skip:跳过 n 元素,配合 limit(n)可实现分页。

在这里插入图片描述
样例:

Stream<String> stream = Stream.of("1", "2", "2", "1", "7", "9");
stream.skip(3).forEach(System.out::println);// 1 7 9

⑤ concat

  • concat:如果有两个流,希望合并为一个流,那么可以使用Stream接口的静态方法concat。

样例:

// 创建一个Stream流
Stream<String> stream1 = Stream.of("1", "2", "3");
// 获取一个Stream流
String[] arr = {"11", "12", "13"};
Stream<String> stream2 = Stream.of(arr);
// 把以上两个流组合为一个流
Stream<String> concat = Stream.concat(stream1, stream2);
// 遍历concat流
concat.forEach(i -> System.out.println(i));

2.2、无状态

① filter

  • filter:过滤流中的某些元素。
    在这里插入图片描述
    样例:
List<Integer> list = Arrays.asList(6, 7, 3, 8, 1, 2);
Stream<Integer> stream = list.stream();
stream.filter(x -> x > 5).forEach(System.out::println);// 6 7 8

② map

  • map:将其映射成一个新的元素。

在这里插入图片描述
样例:

List<Integer> integerList = Lists.newArrayList();
integerList.add(15);
integerList.add(32);
integerList.add(5);
// 将Integer类型转换成String.类型
List<String> afterString = integerList.stream().map(i -> String.valueOf(i)).collect(Collectors.toList());// [15, 32, 5]

③ flatMap

  • flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。
    在这里插入图片描述
    样例:
List<String> list1 = Arrays.asList("m,k,l,a","1,3,5,7");
List<String> listNew = list1.stream().flatMap(s -> {
    // 将每个元素转换成一个stream
    String[] split = s.split(",");
    Stream<String> s2 = Arrays.stream(split);
    return s2;
}).collect(Collectors.toList());

System.out.println("处理前的集合:" + list1);// [m,k,l,a, 1,3,5,7]
System.out.println("处理后的集合:" + listNew);// [m, k, l, a, 1, 3, 5, 7]

④ peek

  • peek:peek 操作接收的是一个 Consumer 函数。顾名思义 peek 操作会按照 Consumer
    函数提供的逻辑去消费流中的每一个元素,同时有可能改变元素内部的一些属性。

在这里插入图片描述
样例:

Stream<String> stream = Stream.of("hello", "felord.cn");
stream.peek(System.out::println);// 空

执行之后,控制台并没有输出任何字符串,这是因为流的生命周期有三个阶段:

  • 起始生成阶段。
  • 中间操作会逐一获取元素并进行处理。可有可无。所有中间操作都是惰性的,因此,流在管道中流动之前,任何操作都不会产生任何影响。
  • 终端操作。通常分为 最终的消费 (foreach 之类的)和 归纳 (collect)两类。还有重要的一点就是终端操作启动了流在管道中的流动。

所以,上面的代码是因为缺少了终端操作,因此,我们改成如下即可:

Stream<String> stream = Stream.of("hello", "felord.cn");
stream.peek(System.out::println).collect(Collectors.toList());// hello felord.cn

重点:peek VS map

peek 操作 一般用于不想改变流中元素本身的类型或者只想元素的内部状态时;

而 map 则用于改变流中元素本身类型,即从元素中派生出另一种类型的操作。

⑤ mapToInt、mapToLong、mapToDouble、flatMapToDouble、flatMapToInt、flatMapToLong

  • 以上这些操作是map和flatMap的特例版,也就是针对特定的数据类型进行映射处理。

样例:

Stream<String> stream = Stream.of("hello", "felord.cn");
stream.mapToInt(s->s.length()).forEach(System.out::println);// 5 9

并且这些指定类型的流,还有另外一些常用的方法,也是很好用的,可以参考:IntStream、LongStream、DoubleStream。

⑥ unordered

  • unordered:操作不会执行任何操作来显式地对流进行排序。它的作用是消除了流必须保持有序的约束,从而允许后续操作使用不必考虑排序的优化。

样例:

public static void main(String[] args) {
	 Stream.of(5, 1, 2, 6, 3, 7, 4).unordered().forEach(System.out::println);
     Stream.of(5, 1, 2, 6, 3, 7,4).unordered().parallel().forEach(System.out::println);
}
 
 
//两次输出结果对比(方便比较,写在一起)
第一遍:          第二遍:
//第一行代码输出   //第一行代码输出
5                 5
1                 1
2                 2
6                 6
3                 3
7                 7
4                 4
 
//第二行代码输出   //第二行代码输出
3                 3
6                 6
4                 7
7                 5
2                 4
1                 1
5                 2

以上结果,可以看到,虽然用了unordered(),但是第一个循环里的数据顺序并没有被打乱,是不是很好奇?

您可以在Java 8文档中有一下一段内容:

对于顺序流,顺序的存在与否不会影响性能,只影响确定性。如果流是顺序的,则在相同的源上重复执行相同的流管道将产生相同的结果;

如果是非顺序流,重复执行可能会产生不同的结果。 对于并行流,放宽排序约束有时可以实现更高效的执行。

在流有序时, 但用户不特别关心该顺序的情况下,使用 unordered 明确地对流进行去除有序约束可以改善某些有状态或终端操作的并行性能。

3、终结操作

3.1、短路操作

① anyMatch

  • anyMatch:接收一个 Predicate 函数,只要流中有一个元素满足条件则返回 true,否则返回 false。

样例:

Stream<Integer> stream = Stream.of(3, 1, 7, 12);
System.out.println(stream.anyMatch(s -> s > 1));// true

② allMatch

  • allMatch:接收一个 Predicate 函数,当流中每个元素都符合条件时才返回 true,否则返回 false。

样例:

Stream<Integer> stream = Stream.of(3, 1, 7, 12);
System.out.println(stream.allMatch(s -> s > 10));// false

③ noneMatch

  • noneMatch:方法在没有元素匹配时返回true。

样例:

Stream<Integer> stream = Stream.of(3, 1, 7, 12);
System.out.println(stream.noneMatch(s -> s > 10));// false

④ findFirst

  • findFirst:返回流中第一个元素。

样例:

Stream<Integer> stream = Stream.of(3, 1, 12, 16, 9);
System.out.println(stream.findFirst().get());// 3

// filter处理
// System.out.println(stream.filter(s -> s > 3).findFirst().get());// 12

⑤ findAny

  • findAny方法可以在集合中只要找到任何一个所匹配的元素,就返回,此方法在对流并行执行时十分有效(任何片段中发现第一个匹配元素都会结束计算,串行流中和findFirst返回一样。

样例:

List<String> strAry = Arrays.asList("Jhonny", "David", "Jack", "Duke", "Jill", "Dany", "Julia", "Jenish", "Divya");

String result = strAry.parallelStream().filter(s -> s.startsWith("J")).findAny().get();// Jill
String result2 = strAry.stream().filter(s -> s.startsWith("J")).findAny().get();// Jhonny

3.2、非短路操作

① forEach

  • forEach:遍历流中的元素。

样例:

List<String> strAry = Arrays.asList( "Jhonny", "David", "Jack", "Duke", "Jill","Dany","Julia","Jenish","Divya");

strAry.stream().forEach(s-> {
    if("Jack".equalsIgnoreCase(s)) System.out.println(s);// Jack
});

② forEachOrdered

  • forEachOrdered:该方法接收一个 Lambda 表达式,然后按顺序在 Stream 的每一个元素上执行该表达式,forEachOrdered是可以保证循环时元素是按原来的顺序逐个循环的。

样例:

List<String> strAry = Arrays.asList( "Jhonny", "David", "Jack", "Duke", "Jill","Dany","Julia","Jenish","Divya");

strAry.stream().forEachOrdered(s-> {
    if("Jack".equalsIgnoreCase(s)) System.out.println(s);// Jack
});

③ toArray

  • toArray:将流中的元素倒入一个数组。
Object [] toArray();
 
<A> A[] toArray(IntFunction<A[]> generator);

样例:

List<String> strList = Arrays.asList("Jhonny", "David", "Jack", "Duke", "Jill", "Dany", "Julia", "Jenish", "Divya");

Object[] strAryNoArg = strList.stream().toArray();
String[] strAry = strList.stream().toArray(String[]::new);

④ reduce

  • reduce:方法是将流中的元素进行进一步计算的方法。

样例

List<Integer> hearList = Lists.newArrayList();
hearList.add(15);
hearList.add(32);
hearList.add(5);
hearList.add(232);
hearList.add(56);
hearList.add(29);
hearList.add(104);
// 求和
Integer sum = hearList.stream().reduce((x, y) -> x + y).get();
System.out.println("sum:" + sum);// 473
// 简化一下,求和
sum = hearList.stream().reduce(Integer::sum).get();
System.out.println("sum:" + sum);// 473
// 含有初始标识的,求和
sum = hearList.stream().reduce(0, (x, y) -> x + y);
System.out.println("sum:" + sum);// 473
// 对元素的长度进行求和((total,y)->total+y.toString().length(),类似于一个累加器,会被重复调用)
sum = hearList.stream().reduce(0, (total, y) -> total + y.toString().length(),
    (totall, total2) -> totall + total2);
System.out.println("sum:" + sum);// 15
// 简化一下,付元素长度进行求和
sum = hearList.stream().map(Objects::toString).mapToInt(String::length).sum();
System.out.println("sum:" + sum);// 15

⑤ collect

  • collect:称为收集器,是一个终端操作,它接收的参数是将流中的元素累积到汇总结果的各种方式。

第一种方式会比较经常使用到,也比较方便使用,现在先看一看里面常用的一些方法:

工厂方法返回类型用于
toListList把流中所有元素收集到List中
示例:List<Menu> menus=Menu.getMenus.stream().collect(Collectors.toList());
工厂方法返回类型用于
toSetSet把流中所有元素收集到Set中,删除重复项
示例:Set<Menu> menus=Menu.getMenus.stream().collect(Collectors.toSet());
工厂方法返回类型用于
toCollectionCollection把流中所有元素收集到给定的供应源创建的集合中
示例:ArrayList<Menu> menus=Menu.getMenus.stream().collect(Collectors.toCollection(ArrayList::new));
工厂方法返回类型用于
CountingLong计算流中元素个数
示例:Long count=Menu.getMenus.stream().collect(counting);
工厂方法返回类型用于
SummingIntInteger对流中元素的一个整数属性求和
示例:Integer count=Menu.getMenus.stream().collect(summingInt(Menu::getCalories));
工厂方法返回类型用于
averagingIntDouble计算流中元素integer属性的平均值
示例:Double averaging=Menu.getMenus.stream().collect(averagingInt(Menu::getCalories));
工厂方法返回类型用于
JoiningString连接流中每个元素的toString方法生成的字符串
示例:String name=Menu.getMenus.stream().map(Menu::getName).collect(joining(,));
工厂方法返回类型用于
maxByOptional一个包裹了流中按照给定比较器选出的最大元素的optional,如果为空返回的是Optional.empty()
示例:Optional<Menu> fattest=Menu.getMenus.stream().collect(maxBy(Menu::getCalories));
工厂方法返回类型用于
minByOptional一个包裹了流中按照给定比较器选出的最小元素的optional,如果为空返回的是Optional.empty()
示例: Optional<Menu> lessest=Menu.getMenus.stream().collect(minBy(Menu::getCalories));
工厂方法返回类型用于
Reducing归约操作产生的类型从一个作为累加器的初始值开始,利用binaryOperator与流中的元素逐个结合,从而将流归约为单个值
示例:int count=Menu.getMenus.stream().collect(reducing(0,Menu::getCalories,Integer::sum));
工厂方法返回类型用于
collectingAndThen转换函数返回的类型包裹另一个转换器,对其结果应用转换函数
示例:Int count=Menu.getMenus.stream().collect(collectingAndThen(toList(),List::size));
工厂方法返回类型用于
groupingByMap<K,List>根据流中元素的某个值对流中的元素进行分组,并将属性值做为结果map的键
示例:Map<Type,List<Menu>> menuType=Menu.getMenus.stream().collect(groupingby(Menu::getType));
工厂方法返回类型用于
partitioningByMap<Boolean,List>根据流中每个元素应用谓语的结果来对项目进行分区
示例:Map<Boolean,List<Menu>> menuType=Menu.getMenus.stream().collect(partitioningBy(Menu::isType)

第二种方式看起来跟reduce的三个入参的方法有点类似,也可以用来实现filter、map等操作!

流程解析图如下:

在这里插入图片描述

⑥ max

  • max:返回此流的最大元素

样例:

List<Integer> num = Arrays.asList( 4, 5, 6);
num.stream().max(Integer::compareTo).ifPresent(System.out::println);// 6

⑦ min

  • min:返回此流的最小元素

样例:

List<Integer> num = Arrays.asList( 4, 5, 6);
num.stream().min(Integer::compareTo).ifPresent(System.out::println);// 4

⑧ count

  • count:返回此流中的元素计数

样例:

List<Integer> num = Arrays.asList( 4, 5, 6);
System.out.println(num.stream().count());// 3

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

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

相关文章

如何快速升级 Cocos Shader 版本,以简易水shader为例

白背景讲述如何 将一份 3.0.0 版本的水shader 升级至 Cocos Creator 3.6 。希望对大家有所帮助。环境Cocos Creator 3.6.2效果玉此处是鱼&#x1f41f;&#xff0c;介绍如何使用在资源管理器中新建着色器(Effect)复制 文末的 mywater.effect 代码至当前文件在资源管理器中新建材…

Ai绘画生成软件哪个好用?这款AI作画的二次元太精致了

Ai绘画生成软件哪个好用呢&#xff1f;今天小编给大家推荐一款AI作画神器&#xff0c;用它生成的二次元真的是超级惊艳&#xff0c;每天每个手机号可以免费生成多张画作。 我们打开数画ai绘画&#xff0c;这是一款国产软件&#xff0c;使用的是自身研发的算法&#xff0c;目前…

Vue3+TypeScript系统学习(十五) - 详解Vue3 Composition API(二)

前面给大家分享了Options API语法中代码的复用、Options API编码的优缺点&#xff0c;以及setup函数&#xff0c;响应式API等&#xff0c;这次将给大家分享Vue3 Composition API中的计算属性&#xff0c;侦听器&#xff0c;生命周期函数&#xff0c;Provide和Inject等。 1.1 co…

商户绑卡银行卡流程设计优化

一、背景 历史商户系统&#xff0c;断断续续经过好多人开发&#xff0c;商户绑卡流程数据好多地方不同步。 商户绑卡会调用支付平台进行绑卡&#xff0c;但是历史平台将数据留存了一份&#xff0c;所以目前现状&#xff0c;商户平台维护一份数据&#xff0c;支付平台维护一份数…

吴恩达机器学习课程笔记:模型描述、假设函数、代价函数

1.吴恩达机器学习课程笔记&#xff1a;模型描述、假设函数、代价函数 吴恩达机器学习课程笔记&#xff1a;模型描述 吴恩达机器学习课程笔记&#xff1a;代价函数 仅作为个人学习笔记&#xff0c;若各位大佬发现错误请指正 什么是模型&#xff1f; 机器学习模型简单来说&#…

玩转数据结构前言

本章为数据结构学习前的一些学习方法建议 51刷题法 leetcode中文站点: https://leetcode-cn.com leetcode国际站点: https://leetcode.com 刷题方法 Round1 1.读题&#xff0c;思考&#xff0c;4-6分钟内有思路立马写&#xff0c;15分钟内写不出来直接放弃 有思路先别管算…

使用mongostat命令实现zabbix监控mongodb

zabbix监控mongodbmongostat命令监控脚本参考zabbix配置mongostat命令 mongostat是mongodb自带的状态检测工具&#xff0c;可以使用这个命令获取mongodb的当前运行状态&#xff0c;并输出。我们使用这个命令获取mongodb的状态。 本示例中是一个3节点的复制集群&#xff08;一…

调用方系统禁止依赖传递后如何排查本系统所缺少依赖

订单系统依赖了好多其他系统&#xff0c;但当其他系统的service-api的包里依赖项加入了禁止依赖后&#xff0c;订单系统启动就会报错&#xff0c;具体排查那些包被禁止依赖了&#xff0c;方案如下 举例&#xff1a;会员系统后个包加入了禁止依赖<optional>true</opti…

Java中set的基本操作

文章目录1、定义Set2、增删改操作&#xff08;1&#xff09;新增&#xff08;2&#xff09;删出&#xff08;3&#xff09;修改3、访问set4、遍历set&#xff08;1&#xff09;foreach遍历&#xff08;2&#xff09;iterator迭代器遍历5、set转换6、其他操作set是一个无序的集合…

深度解析源码之SpringMVC文件上传为什么要用POST请求还要设置请求头

深度解析源码之SpringMVC文件上传为什么要用POST请求还要设置请求头 从本篇文章开始&#xff0c;来逐步介绍里面每一步的细节处理流程。 首先看到doDispatch方法的第一个重要操作就是校验文件上传请求。代码如下&#xff1a; 这个方法是如何校验文件上传请求的呢&#xff1f;…

软件测试最常用的 SQL 命令 | 通过实例掌握基本查询、条件查询、聚合查询

本文为霍格沃兹测试学院优秀学员学习笔记&#xff0c;汇总了软件测试人员经常使用&#xff0c;必须掌握的 SQL 基础命令1、DML核心CRUD增删改查缩写全称和对应 SQL&#xff1a;* DML 数据操纵语言&#xff1a;Data Manipulation Language* Create 增加&#xff1a;insert* Ret…

工作和学习遇到的技术问题

写在前面 记录工作和学习遇到的技术问题,以求再次遇到可以快速解决。 1&#xff1a;Ubuntu TSL换源报错&#xff1a;Err:1 http://mirrors.aliyun.com/ubuntu focal InRelease 执行如下操作&#xff08;已经操作的则忽略&#xff09;&#xff0c;首先在文件/etc/apt/sources…

Vue.js 数据双向绑定的实现

前言 在我们使用vue的时候&#xff0c;当数据发生了改变&#xff0c;界面也会跟着更新&#xff0c;但这并不是理所当然的&#xff0c;我们修改数据的时候vue是如何监听数据的改变以及当数据发生改变的时候vue如何让界面刷新的&#xff1f; 当我们修改数据的时候vue是通过es5中…

DataGear 制作基于Vue2、Element UI弹窗效果的数据可视化看板

DataGear 在4.4.0版本新增了dg-chart-manual-render特性&#xff0c;用于手动控制看板内图表的渲染&#xff0c;而非在页面加载时自动渲染。利用这一特性&#xff0c;可以很方便制作具有弹窗效果的数据可视化看板。 本文以Vue2、Element UI 前端框架为例&#xff0c;介绍如何制…

【C语言】通讯录—静态版

前言: 刚学完结构体和枚举&#xff0c;在网上找了个通讯录的项目&#xff0c;用来练手 目标:该通讯录可存储千人个人信息 包括:姓名&#xff0c;年龄&#xff0c;性别&#xff0c;电话&#xff0c;地址 实现功能: 1.添加联系人 2.删除联系人 …

Web 安全漏洞之 XSS 攻击

什么是 XSS 攻击 XSS&#xff08;Cross-Site Scripting&#xff09;又称跨站脚本&#xff0c;XSS的重点不在于跨站点&#xff0c;而是在于脚本的执行。XSS是一种经常出现在 Web 应用程序中的计算机安全漏洞&#xff0c;是由于 Web 应用程序对用户的输入过滤不足而产生的。 常…

MyBatis -- 多表查询

MyBatis -- 多表查询一、准备工作二、多表查询属性名与字段名不匹配一、准备工作 博客系统场景。 创建库、表&#xff1a; -- 创建数据库 drop database if exists mycnblog; create database mycnblog DEFAULT CHARACTER SET utf8mb4;-- 使用数据数据 use mycnblog;-- 创建…

小程序样式和组件基础

小程序样式和组件基础小程序样式样式wxss简介响应式单位rpx其它css单位支持的单位内置组件简介image组件-基础组件介绍常用属性示例image组件-懒加载与基础库版本用法swiper组件组件介绍常用属性示例navigator组件-基础组件介绍常用属性示例navigator组件-页面栈页面栈返回按钮…

常用windows自带程序对应的命令

敲winr键&#xff0c;调出 运行 框&#xff1b; 输入命令回车&#xff0c;打开对应程序&#xff1b; 输入cmd&#xff0c;调出命令行窗口&#xff1b; gpedit&#xff0c;组策略编辑器&#xff0c; 有的电脑没有组策略编辑器&#xff1b; 资源管理器&#xff1b; dvdplay&…

【BP靶场portswigger-客户端15】基于DOM的漏洞-7个实验(全)

前言&#xff1a; 介绍&#xff1a; 博主&#xff1a;网络安全领域狂热爱好者&#xff08;承诺在CSDN永久无偿分享文章&#xff09;。 殊荣&#xff1a;CSDN网络安全领域优质创作者&#xff0c;2022年双十一业务安全保卫战-某厂第一名&#xff0c;某厂特邀数字业务安全研究员&…