当前位置: 首页 > news >正文

MapStruct应用实战及BeanUtils性能比较

目录

    • 1、MapStruct介绍
    • 2、应用设置
      • 2.1 Maven依赖
    • 3、功能实战
      • 3.1 常用注解
      • 3.2 基本映射
        • 3.2.1 定义映射器的Java接口
        • 3.2.2 测试验证
      • 3.3 参数引用映射
        • 3.3.1 定义映射器的Java接口
        • 3.3.2 测试验证
      • 3.4 多对象参数映射
        • 3.4.1 定义映射器的Java接口
        • 3.4.2 测试验证
        • 3.4.3 注意点
      • 3.5 嵌套映射
        • 3.5.1 定义映射器的Java接口
        • 3.5.2 测试验证
        • 3.5.3 注意点
      • 3.6 对象更新
        • 3.6.1 定义映射器的Java接口
        • 3.6.2 测试验证
        • 3.6.3 注意点
    • 4、性能比较
      • 4.1 Apache BeanUtils 与 MapStruct比较
      • 4.2 Hutool BeanUtil与 MapStruct比较
      • 4.3 Spring BeanUtils 与 MapStruct比较
      • 4.4 Cglib BeanCopier 与 MapStruct比较
      • 4.4 性能对比结果(5次平均值)


1、MapStruct介绍

MapStruct官方文档

  1. MapStruct是一个Java注释处理器,用于生成类型安全的bean映射类,它基于约定优于配置方法,极大地简化了 Java bean
    类型之间映射的实现。
  2. 您所要做的就是定义一个mapper接口,该接口声明任何所需的映射方法。在编译期间,MapStruct将生成此接口的实现。此实现使用普通的Java方法调用来在源对象和目标对象之间进行映射,即没有反射或类似。
  3. 与手工编写映射代码相比,MapStruct通过生成繁琐且易于编写的代码来节省时间。遵循约定优于配置方法,MapStruct使用合理的默认值,但在配置或实现特殊行为时会采取措施。
  4. 与动态映射框架相比,MapStruct具有以下优势:
  • 通过使用普通方法调用而不是反射来快速执行

  • 编译时类型安全:只能映射相互映射的对象和属性,不会将订单实体意外映射到客户DTO等。

  • 在构建时清除错误报告,如果

    • 映射不完整(并非所有目标属性都已映射)
    • 映射不正确(找不到合适的映射方法或类型转换)

2、应用设置

2.1 Maven依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.siayou</groupId><artifactId>mapstruct-demo</artifactId><version>1.0-SNAPSHOT</version><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><org.mapstruct.version>1.4.1.Final</org.mapstruct.version><org.projectlombok.version>1.18.12</org.projectlombok.version></properties><dependencies><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct</artifactId><version>${org.mapstruct.version}</version></dependency><!-- lombok dependencies should not end up on classpath --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${org.projectlombok.version}</version><scope>provided</scope></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>1.8</source><target>1.8</target><annotationProcessorPaths><path><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${org.projectlombok.version}</version></path><path><groupId>org.mapstruct</groupId><artifactId>mapstruct-processor</artifactId><version>${org.mapstruct.version}</version></path></annotationProcessorPaths></configuration></plugin></plugins></build>
</project>

3、功能实战

3.1 常用注解

  • @Mapper 标记这个接口作为一个映射接口,并且是编译时 MapStruct 处理器的入口
  • @Mapping 解决源对象和目标对象中,属性名字不同的情况
  • @Mappings 当存在多个 @Mapping 需要配置;可以通过 @Mappings 批量指定
  • Mappers.getMapper Mapper 的 class 获取自动生成的实现对象,从而让客户端可以访问 Mapper 接口的实现

3.2 基本映射

3.2.1 定义映射器的Java接口
@Mapper
public interface StudentMapper {StudentMapper INSTANCE = Mappers.getMapper(StudentMapper.class);//mapper可以进行字段映射,改变字段类型,指定格式化的方式,包括一些日期的默认处理。//无论date转string,还是string转date,都是用dateFormat@Mapping(source = "gender.name", target = "gender")@Mapping(source = "birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")StudentVO student2StudentVO(Student student);
}
// @Data 在编译时会自动添加 Getter、Setter、equals、canEqual、hasCode、toString 等方法,高效且代码非常简洁。
// @Builder 可代替需要的很多构造函数,解决了某个类有很多构造函数的情况。
// @AllArgsConstructor 在编译时会自动添加一个含有所有已声明字段的构造函数,不必再手动编写含有所有已声明字段的构造函数。
// @NoArgsConstructor 在编译时会自动添加一个无参的构造函数,不必再手动编写无参构造函数。
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Student {//姓名private String name;//年龄private int age;//性别private GenderEnum gender;//身高private Double height;//生日private Date birthday;
}@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class StudentVO {//姓名private String name;//年龄private int age;//性别private String gender;//身高private Double height;//生日private String birthday;
}public enum GenderEnum {Male("1", "男"),Female("0", "女");private String code;private String name;public String getCode() {return this.code;}public String getName() {return this.name;}GenderEnum(String code, String name) {this.code = code;this.name = name;}
}
3.2.2 测试验证
    public static void main(String[] args) {Student student = Student.builder().name("张三").age(16).gender(GenderEnum.Male).height(174.3).birthday(new Date()).build();System.out.println(student);StudentVO studentVO = StudentMapper.INSTANCE.student2StudentVO(student);System.out.println(studentVO);}//测试结果
Student(name=张三, age=16, gender=Male, height=174.3, birthday=Fri Sep 22 16:22:38 CST 2023)
StudentVO(name=张三, age=16, gender=, height=174.3, birthday=2023-09-22 16:22:38)

3.3 参数引用映射

3.3.1 定义映射器的Java接口
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class StudentVO {//姓名private String name;//年龄private int age;//性别private String gender;//身高private Double height;//生日private String birthday;private ExtendDto extendDto;
}@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Student {//姓名private String name;//年龄private int age;//性别private GenderEnum gender;//身高private Double height;//生日private Date birthday;private ExtendDto extendDto;
}@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ExtendDto {//邮箱private String email;//地址private String address;//电话private String phone;
}@Mapper
public interface StudentMapper {@Mapping(source = "student.birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")@Mapping(source = "email", target = "extendDto.email")StudentVO studentTwoStudentVO(Student student,String email);
}
3.3.2 测试验证
public static void main(String[] args) {Student student = Student.builder().name("李四").age(16).gender(GenderEnum.Male).height(174.3).birthday(new Date()).build();System.out.println(student);StudentVO studentVO = StudentMapper.INSTANCE.studentTwoStudentVO(student,"dmjxsy@126.com");System.out.println(studentVO);}//测试结果
Student(name=李四, age=16, gender=Male, height=174.3, birthday=Thu Sep 28 15:12:36 CST 2023, extendDto=null)
StudentVO(name=李四, age=16, gender=Male, height=174.3, birthday=2023-09-28 15:12:36, extendDto=ExtendDto(email=dmjxsy@126.com, address=null, phone=null))

3.4 多对象参数映射

3.4.1 定义映射器的Java接口
    @Mapping(source = "student.birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")@Mapping(source = "extendDto", target = "extendDto")StudentVO studentMapStudentVO(Student student,ExtendDto extendDto);
3.4.2 测试验证
    public static void main(String[] args) {Student student = Student.builder().name("李四").age(16).gender(GenderEnum.Male).height(174.3).birthday(new Date()).build();ExtendDto extendDto = ExtendDto.builder().email("dmjxsy@126.com").phone("119").address("陕西").build();System.out.println(student);System.out.println(extendDto);StudentVO studentVO = StudentMapper.INSTANCE.studentMapStudentVO(student,extendDto);System.out.println(studentVO);
}//测试结果
Student(name=李四, age=16, gender=Male, height=174.3, birthday=Thu Sep 28 15:24:18 CST 2023, extendDto=null)
ExtendDto(email=dmjxsy@126.com, address=陕西, phone=119)
StudentVO(name=李四, age=16, gender=Male, height=174.3, birthday=2023-09-28 15:24:18, extendDto=ExtendDto(email=dmjxsy@126.com, address=陕西, phone=119))}
3.4.3 注意点

当配置了参数时,在配置对象属性关系映射时,也要显示的指明对象参数的名称。如@Mapping(source = “student.birthday”, target = “birthday”) 就显示指明了 source = “student.birthday” 。

3.5 嵌套映射

3.5.1 定义映射器的Java接口
    @Mapping(source = "student.birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")@Mapping(source = "extendDto", target = ".")StudentVO studentMapStudentVO(Student student);
3.5.2 测试验证
    public static void main(String[] args) {Student student = Student.builder().name("李四").age(16).gender(GenderEnum.Male).height(174.3).birthday(new Date()).extendDto( ExtendDto.builder().email("dmjxsy@126.com").phone("110").address("陕西").build()).build();System.out.println(student);StudentVO studentVO = StudentMapper.INSTANCE.studentMapStudentVO(student);System.out.println(studentVO);}
//测试结果
Student(name=李四, age=16, gender=Male, height=174.3, birthday=Thu Sep 28 15:31:14 CST 2023, extendDto=ExtendDto(email=dmjxsy@126.com, address=陕西, phone=110))
StudentVO(name=李四, age=16, gender=Male, height=174.3, birthday=2023-09-28 15:31:14, extendDto=ExtendDto(email=dmjxsy@126.com, address=陕西, phone=110))
3.5.3 注意点

使用 “ . ” ,将一个嵌套的bean的值合并到一个扁平化的对象中。

3.6 对象更新

3.6.1 定义映射器的Java接口
    @Mapping(source = "student.birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")@Mapping(source = "extendDto", target = ".")
//    @Mapping(source = "name",target = "name",  ignore = true)void updateStudent(Student student,@MappingTarget StudentVO studentVO);@Mapping(source = "student.birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")@Mapping(source = "extendDto", target = ".")@Mapping(source = "name",target = "name",  ignore = true)void updateStudent(Student student,@MappingTarget StudentVO studentVO);
3.6.2 测试验证
public static void main(String[] args) {Student student = Student.builder().name("李四").age(16).gender(GenderEnum.Male).height(174.3).birthday(new Date()).extendDto( ExtendDto.builder().email("dmjxsy@126.com").phone("110").address("陕西").build()).build();StudentVO studentVO = StudentVO.builder().name("王五").age(20).height(204.3).birthday("2020-01-01 12:11:11").extendDto( ExtendDto.builder().email("dmjxsy@163.com").phone("110110119").address("陕西西安").build()).build();System.out.println("更新前 student:"+student.toString());System.out.println("更新前 studentVO:"+studentVO.toString());StudentMapper.INSTANCE.updateStudent(student,studentVO);System.out.println("更新后 student:"+student.toString());System.out.println("更新后 studentVO:"+studentVO.toString());}
//测试结果
更新前 :Student(name=李四, age=16, gender=Male, height=174.3, birthday=Thu Sep 28 15:56:35 CST 2023, extendDto=ExtendDto(email=dmjxsy@126.com, address=陕西, phone=110))
更新前 :StudentVO(name=王五, age=20, gender=null, height=204.3, birthday=2020-01-01 12:11:11, extendDto=ExtendDto(email=dmjxsy@163.com, address=陕西西安, phone=110110119))
更新后 :Student(name=李四, age=16, gender=Male, height=174.3, birthday=Thu Sep 28 15:56:35 CST 2023, extendDto=ExtendDto(email=dmjxsy@126.com, address=陕西, phone=110))
更新后 :StudentVO(name=李四, age=16, gender=Male, height=174.3, birthday=2023-09-28 15:56:35, extendDto=ExtendDto(email=dmjxsy@126.com, address=陕西, phone=110))
//添加 @Mapping(source = "name",target = "name",  ignore = true)
更新前 :Student(name=李四, age=16, gender=Male, height=174.3, birthday=Thu Sep 28 15:57:39 CST 2023, extendDto=ExtendDto(email=dmjxsy@126.com, address=陕西, phone=110))
更新前 :StudentVO(name=王五, age=20, gender=null, height=204.3, birthday=2020-01-01 12:11:11, extendDto=ExtendDto(email=dmjxsy@163.com, address=陕西西安, phone=110110119))
更新后 :Student(name=李四, age=16, gender=Male, height=174.3, birthday=Thu Sep 28 15:57:39 CST 2023, extendDto=ExtendDto(email=dmjxsy@126.com, address=陕西, phone=110))
更新后 :StudentVO(name=王五, age=16, gender=Male, height=174.3, birthday=2023-09-28 15:57:39, extendDto=ExtendDto(email=dmjxsy@126.com, address=陕西, phone=110))
3.6.3 注意点

@MappingTarget 使用改注解标记目标对象我们就可以更新该对象的值。如果想不更新某个值,可以给加一个ignore = true的标签来忽略。

4、性能比较

4.1 Apache BeanUtils 与 MapStruct比较

 public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {for (int i = 0; i < 10; i++) {Long start = System.currentTimeMillis();for (int i1 = 0; i1 < 1000000; i1++) {Student student = Student.builder().name("小明").age(6).gender(GenderEnum.Male).height(121.1).birthday(new Date()).build();StudentVO studentVO = new StudentVO();org.apache.commons.beanutils.BeanUtils.copyProperties(studentVO, student);}System.out.println("org.apache.commons.beanutils.BeanUtils第"+ i +"次执行---100W次转换耗时:" + (System.currentTimeMillis() - start));Long start2 = System.currentTimeMillis();for (int i1 = 0; i1 < 1000000; i1++) {Student student = Student.builder().name("小明").age(6).gender(GenderEnum.Male).height(121.1).birthday(new Date()).build();StudentMapper.INSTANCE.student2StudentVO(student);}System.out.println("MapStruct第"+ i +"次执行-----100W次转换耗时:" + (System.currentTimeMillis() - start2));}}
//测试结果
org.apache.commons.beanutils.BeanUtils0次执行---100W次转换耗时:11854
MapStruct0次执行-----100W次转换耗时:1981
org.apache.commons.beanutils.BeanUtils1次执行---100W次转换耗时:10828
MapStruct1次执行-----100W次转换耗时:2080
org.apache.commons.beanutils.BeanUtils2次执行---100W次转换耗时:9894
MapStruct2次执行-----100W次转换耗时:1891
org.apache.commons.beanutils.BeanUtils3次执行---100W次转换耗时:9543
MapStruct3次执行-----100W次转换耗时:1735
org.apache.commons.beanutils.BeanUtils4次执行---100W次转换耗时:6862
MapStruct4次执行-----100W次转换耗时:1958

4.2 Hutool BeanUtil与 MapStruct比较

public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {for (int i = 0; i < 5; i++) {Long start = System.currentTimeMillis();for (int i1 = 0; i1 < 1000000; i1++) {Student student = Student.builder().name("小明").age(6).gender(GenderEnum.Male).height(121.1).birthday(new Date()).build();StudentVO studentVO = new StudentVO();cn.hutool.core.bean.BeanUtil.copyProperties(studentVO,student,true);}System.out.println("cn.hutool.core.bean.BeanUtil第"+ i +"次执行---100W次转换耗时:" + (System.currentTimeMillis() - start));Long start2 = System.currentTimeMillis();for (int i1 = 0; i1 < 1000000; i1++) {Student student = Student.builder().name("小明").age(6).gender(GenderEnum.Male).height(121.1).birthday(new Date()).build();StudentMapper.INSTANCE.student2StudentVO(student);}System.out.println("MapStruct第"+ i +"次执行-----100W次转换耗时:" + (System.currentTimeMillis() - start2));}}
//测试结果
cn.hutool.core.bean.BeanUtil0次执行---100W次转换耗时:7169
MapStruct0次执行-----100W次转换耗时:2538
cn.hutool.core.bean.BeanUtil1次执行---100W次转换耗时:4797
MapStruct1次执行-----100W次转换耗时:1707
cn.hutool.core.bean.BeanUtil2次执行---100W次转换耗时:5582
MapStruct2次执行-----100W次转换耗时:1505
cn.hutool.core.bean.BeanUtil3次执行---100W次转换耗时:4906
MapStruct3次执行-----100W次转换耗时:1322
cn.hutool.core.bean.BeanUtil4次执行---100W次转换耗时:3789
MapStruct4次执行-----100W次转换耗时:1635

4.3 Spring BeanUtils 与 MapStruct比较

    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {for (int i = 0; i < 5; i++) {Long start = System.currentTimeMillis();for (int i1 = 0; i1 < 1000000; i1++) {Student student = Student.builder().name("小明").age(6).gender(GenderEnum.Male).height(121.1).birthday(new Date()).build();StudentVO studentVO = new StudentVO();org.springframework.beans.BeanUtils.copyProperties(studentVO, student);}System.out.println("org.springframework.beans.BeanUtils第"+ i +"次执行---100W次转换耗时:" + (System.currentTimeMillis() - start));Long start2 = System.currentTimeMillis();for (int i1 = 0; i1 < 1000000; i1++) {Student student = Student.builder().name("小明").age(6).gender(GenderEnum.Male).height(121.1).birthday(new Date()).build();StudentMapper.INSTANCE.student2StudentVO(student);}System.out.println("MapStruct第"+ i +"次执行-----100W次转换耗时:" + (System.currentTimeMillis() - start2));}}
//测试结果
org.springframework.beans.BeanUtils0次执行---100W次转换耗时:1156
MapStruct0次执行-----100W次转换耗时:3376
org.springframework.beans.BeanUtils1次执行---100W次转换耗时:290
MapStruct1次执行-----100W次转换耗时:1367
org.springframework.beans.BeanUtils2次执行---100W次转换耗时:506
MapStruct2次执行-----100W次转换耗时:1586
org.springframework.beans.BeanUtils3次执行---100W次转换耗时:318
MapStruct3次执行-----100W次转换耗时:1319
org.springframework.beans.BeanUtils4次执行---100W次转换耗时:304
MapStruct4次执行-----100W次转换耗时:1226

4.4 Cglib BeanCopier 与 MapStruct比较

 public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {for (int i = 0; i < 5; i++) {Long start = System.currentTimeMillis();for (int i1 = 0; i1 < 1000000; i1++) {Student student = Student.builder().name("小明").age(6).gender(GenderEnum.Male).height(121.1).birthday(new Date()).build();StudentVO studentVO = new StudentVO();org.springframework.cglib.beans.BeanCopier.create(StudentVO.class, Student.class, false);}System.out.println("org.springframework.cglib.beans.BeanCopier第"+ i +"次执行---100W次转换耗时:" + (System.currentTimeMillis() - start));Long start2 = System.currentTimeMillis();for (int i1 = 0; i1 < 1000000; i1++) {Student student = Student.builder().name("小明").age(6).gender(GenderEnum.Male).height(121.1).birthday(new Date()).build();StudentMapper.INSTANCE.student2StudentVO(student);}System.out.println("MapStruct第"+ i +"次执行-----100W次转换耗时:" + (System.currentTimeMillis() - start2));}}//测试结果
org.springframework.cglib.beans.BeanCopier0次执行---100W次转换耗时:725
MapStruct0次执行-----100W次转换耗时:4524
org.springframework.cglib.beans.BeanCopier1次执行---100W次转换耗时:210
MapStruct1次执行-----100W次转换耗时:1663
org.springframework.cglib.beans.BeanCopier2次执行---100W次转换耗时:72
MapStruct2次执行-----100W次转换耗时:1446
org.springframework.cglib.beans.BeanCopier3次执行---100W次转换耗时:80
MapStruct3次执行-----100W次转换耗时:1482
org.springframework.cglib.beans.BeanCopier4次执行---100W次转换耗时:84
MapStruct4次执行-----100W次转换耗时:1441

4.4 性能对比结果(5次平均值)

工具类执行1000执行1w执行10w执行100w
Apache BeanUtils103.2323.31105.87227.8
Hutool BeanUtil111249.2925.44420.6
Spring BeanUtils8093.4206.4728.6
Cglib BeanCopier86.4103.8103.8263
MapStruct53.6137.8447.82672.2

相关文章:

MapStruct应用实战及BeanUtils性能比较

目录 1、MapStruct介绍2、应用设置2.1 Maven依赖 3、功能实战3.1 常用注解3.2 基本映射3.2.1 定义映射器的Java接口3.2.2 测试验证 3.3 参数引用映射3.3.1 定义映射器的Java接口3.3.2 测试验证 3.4 多对象参数映射3.4.1 定义映射器的Java接口3.4.2 测试验证3.4.3 注意点 3.5 嵌…...

ISP技术概述

原本或许是为了对冲手机系统和APP设计无力感而诞生的拍照功能,现今却成为了众手机厂家除背部设计外为数不多可“卷”的地方,自拍、全景、夜景、小视频等旺盛的需求让这一技术的江湖地位迅速变化。对圈内人士而言,这一波变化带来的后摄、双摄、多摄、暗光、防抖、广角、长焦、…...

CSDN: ABTest流量分层分桶机制

在互联网行业&#xff0c;无论是构建搜索推荐系统&#xff0c;还是智能营销等场景&#xff0c;都是围绕用户进行不同的实验&#xff0c;从各项指标上观察用户对不同交互、流程、策略、算法等反馈&#xff0c;进而对产品进行迭代改进。 本文的goal&#xff1a;在进行了模型的线下…...

【小余送书第一期】《数据要素安全流通》参与活动,即有机会中奖哦!!

目录 1、背景介绍 2、本书编撰背景 3、本书亮点 4、本书主要内容 5、活动须知 1、背景介绍 随着大数据、云计算、人工智能等新兴技术的迅猛发展&#xff0c;数据已经成为我国经济社会发展的五大生产要素之一&#xff0c;《网络安全法》《个人信息保护法》《数据安全法》的…...

蓝牙核心规范(V5.4)10.7-BLE 入门笔记之L2CAP

1.概述 ATT属性用于两个设备,一个扮演客户端的角色,另一个扮演服务器的角色。服务器公开一系列称为属性的复合数据项。这些属性由服务器按索引列表组织在称为属性表的列表中。 每个属性包含一个句柄、一个通用唯一标识符(UUID)、一个值和一组权限。 句柄是一个唯一的索引…...

VUE之正则表达式全集整理

一、正则表达式的基本语法 var expression /pattern(模式)/flags(标识符); 二、如何创建正则表达式 1.字面量创建 代码如下&#xff1a; //匹配字符串中所有“at”的实例 var e /at/g; //匹配第一个“bat”或“cat”,不区分大小写 var e /[bc]at/i; 2.RegExp构造函数创…...

Python 中的字符串基础与应用

在Python中&#xff0c;字符串可以用单引号或双引号括起来。‘hello’ 与 “hello” 是相同的。您可以使用print()函数显示字符串文字&#xff1a; 示例&#xff1a; print("Hello") print(Hello)将字符串分配给变量是通过变量名后跟等号和字符串完成的&#xff1a…...

C++:如何实现数组元素逆置?多种方法

方法1&#xff1a;使用额外的数组 这是一种比较简单的方法&#xff0c;它创建一个额外的数组来存储逆置后的元素&#xff0c;然后将其复制回原始数组。 #include <iostream>void reverseArray(int arr[], int size) {int reversed[size];for (int i 0; i < size; i)…...

php框架thinkPHP6的安装教程

1&#xff0c;composer官网下载最新版本 composerhttps://getcomposer.org/download/ 2&#xff0c;双击下载后的运行文件&#xff0c;一直点击next就行了 上面这个路径根据自己安装的php版本位置选择&#xff08;没有的可以下载一个phpstudy&#xff09;&#xff0c;最后需要…...

PTA程序辅助实验平台——2023年软件设计综合实践_3(分支与循环)

第一题&#xff1a;7-1 印第安男孩 - C/C 分支与循环 朵拉编程的时候也想顺便练习英语。她编程从键盘读入一个整数n&#xff0c;如果n值为0或者1&#xff0c;向屏幕输出“0 indian boy.”或“1 indian boy.”&#xff1b;如果n大于1&#xff0c;比如9&#xff0c;则输出“9 in…...

【C语言数据结构】线性表-链式存储-单链表

线性表-链式存储-单链表 代码实现 代码实现 #include<stdio.h> #include<stdlib.h> #include<stdbool.h>//定义元素数据类型 #define ElemType int//定义结点结构体 typedef struct LNode {//数据域&#xff0c;说白了就是存放当前节点的数据的。ElemType d…...

tp8 Editor.md

Editor.md - 开源在线 Markdown 编辑器 放于public文件夹下 html代码&#xff1a; <div class"layui-col-md12" id"content"><textarea name"content" placeholder"详情" class"layui-textarea">{notempty nam…...

LM小型可编程控制器软件(基于CoDeSys)笔记三十一:保持变量和非保持变量

所谓变量&#xff0c;就是用字母、数字和下划线组成的一个标识符。 按照数据类型的不同&#xff0c;变量可以分为标准类型和用户自定义类型。其中标准类型包括布尔型 &#xff08; BOOL &#xff09;、整型&#xff08; INT &#xff09;、实型&#xff08; REAL &#xff09…...

「C++之STL」关于在模拟实现STL容器中的深浅拷贝问题

文章目录 前言杨辉三角深浅拷贝问题模拟实现的vector对题目杨辉三角引发的程序崩溃原因解决办法 前言 在学习STL容器中,不仅需要学会容器的使用,同时也需要了解容器的大体框架以及各个函数的模拟实现才能更好的去了解这个容器; 杨辉三角 在LeetCode中有一道这样的题目,给定一…...

文件内容显示

目录 1.浏览普通文件 1.1. 文件内容查看 1.1.1. cat 命令 例&#xff1a; 1.1.2 扩展tac命令&#xff1a; 1.1.3. more 命令 1.1.4. less命令 1.1.5. head命令 1.1.6. tail命令 1.2. 文件属性信息查看 1.2.1. file 命令 1.2.2. stat 命令 2. 文件内容过滤…...

Milvus+Attu

Milvus 1.下载 https://github.com/milvus-io/milvus/releases/wget https://github.com/milvus-io/milvus/releases/download/v2.3.0/milvus-standalone-docker-compose.yml下载milvus-standalone-docker-compose version: 3.5services:etcd:container_name: milvus-etcdim…...

LeetCode算法二叉树—226. 翻转二叉树

目录 226. 翻转二叉树 代码&#xff1a; 运行结果&#xff1a; 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1]示例 2&#xff1a; 输入…...

AI项目十:Swin Transformer目标检测环境搭建

若该文为原创文章&#xff0c;转载请注明原文出处。 Swin Transformer是做什么的这里不做介绍&#xff0c;主要是记录下学习的全过程&#xff0c;Swin Transformer在搭建和训练的过程中&#xff0c;折腾了很久&#xff0c;主要是在折腾环境。 一、AutoDL租用实例 个人没有GP…...

【IPC 通信】信号处理接口 Signal API(5)

收发信号思想是 Linux 程序设计特性之一&#xff0c;一个信号可以认为是一种软中断&#xff0c;通过用来向进程通知异步事件。 本文讲述的 信号处理内容源自 Linux man。本文主要对各 API 进行详细介绍&#xff0c;从而更好的理解信号编程。 kill(2) 遵循 POSIX.1 - 2008 1.库 …...

Arduino PLC IDE

Arduino PLC IDE MCU单片机进入全新的PLC领域概述需要的硬件和软件下一步操作1. Arduino PLC IDE Tool Setup2. Arduino PLC IDE Setup3. Project Setup4. Download the Runtime5. Connect to the Device6. License Activation with Product Key (Portenta Machine Control) 结…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

OPENCV形态学基础之二腐蚀

一.腐蚀的原理 (图1) 数学表达式&#xff1a;dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一&#xff0c;腐蚀跟膨胀属于反向操作&#xff0c;膨胀是把图像图像变大&#xff0c;而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

如何把工业通信协议转换成http websocket

1.现状 工业通信协议多数工作在边缘设备上&#xff0c;比如&#xff1a;PLC、IOT盒子等。上层业务系统需要根据不同的工业协议做对应开发&#xff0c;当设备上用的是modbus从站时&#xff0c;采集设备数据需要开发modbus主站&#xff1b;当设备上用的是西门子PN协议时&#xf…...

RK3568项目(七)--uboot系统之外设与PMIC详解

目录 一、引言 二、按键 ------>2.1、按键种类 ------------>2.1.1、RESET ------------>2.1.2、UPDATE ------------>2.1.3、PWRON 部分 ------------>2.1.4、RK809 PMIC ------------>2.1.5、ADC按键 ------------>2.1.6、ADC按键驱动 ------…...

MySQL用户远程访问权限设置

mysql相关指令 一. MySQL给用户添加远程访问权限1. 创建或者修改用户权限方法一&#xff1a;创建用户并授予远程访问权限方法二&#xff1a;修改现有用户的访问限制方法三&#xff1a;授予特定数据库的特定权限 2. 修改 MySQL 配置文件3. 安全最佳实践4. 测试远程连接5. 撤销权…...

CKA考试知识点分享(2)---ingress

CKA 版本&#xff1a;1.32 第二题是涉及ingress相关。本文不是题目&#xff0c;只是为了学习相关知识点做的实验。 1. 环境准备 需要准备一套K8S集群。 1.1 安装ingress-nginx 下载deploy文件&#xff1a; wget -O controller-v1.12.2.yaml https://raw.githubusercontent…...

多层PCB技术解析:从材料选型到制造工艺的深度实践

在电子设备集成度与信号传输要求不断提升的背景下&#xff0c;多层PCB凭借分层布局优势&#xff0c;成为高速通信、汽车电子、工业控制等领域的核心载体。其通过导电层、绝缘层的交替堆叠&#xff0c;实现复杂电路的立体化设计&#xff0c;显著提升空间利用率与信号完整性。 一…...