struct 订阅
struct即结构体,亦被直接称为“结构”。实际编程时,经常需要用相关的不同类型的数据来描述一个数据对象。例如,描述学生的综合信息时,需要使用学生的学号、姓名、性别、成绩以及家庭住址等不同类型的数据。但是,用相关的不同类型的数据来描述一个数据对象会使编程极为不便。因此,C语言提供了一种称为结构体(struct)的数据类型,以描述需要不同类型数据的数据对象 [1]  。 展开全文
struct即结构体,亦被直接称为“结构”。实际编程时,经常需要用相关的不同类型的数据来描述一个数据对象。例如,描述学生的综合信息时,需要使用学生的学号、姓名、性别、成绩以及家庭住址等不同类型的数据。但是,用相关的不同类型的数据来描述一个数据对象会使编程极为不便。因此,C语言提供了一种称为结构体(struct)的数据类型,以描述需要不同类型数据的数据对象 [1]  。
信息
别    称
结构
类    别
C/C++关键词
构    成
由若干“成员”组成
释    义
一种构造数据类型
中文名
结构体
外文名
Structure type
struct构成
“结构”是一种构造类型,它是由若干“成员”组成的。 每一个成员可以是一个基本数据类型或者又是一个构造类型。 结构即是一种“构造”而成的数据类型, 那么在说明和使用之前必须先定义它,也就是构造它。如同在说明和调用函数之前要先定义一样。  “结构体”是由一些逻辑相关的数据栏或称为“字段”(Field)所构成。例如,一位学生的学号、姓名、生日……即是一条记录,该结构体拥有“姓名”栏、“语文”栏、“英文”栏,而一群学生的记录集合就是一个结构体数组 [2]  。
收起全文
精华内容
下载资源
问答
  • struct
    千次阅读
    2022-02-18 14:24:31

    前言

    在使用分层或者分模块化的项目中,我们可能定义各种各样的O,例如:DO,VO,DTO等等。我们在进行这些对象之间的拷贝时,通过手动写get/set方法进行属性之间的赋值。因为他们之间的属性大部分都是相同的,不仅浪费时间,并且还有大量重复代码。所以,各种框架都添加的对象之间的拷贝的工具类。例如:

    Spring自带了BeanUtils

    Apatch自带的BeanUtils

    Apatch自带的PropertyUtils

    mapstruct提供Mappers

        本文主要介绍MapStruct的基础知识、Mapstruct的优缺点、Mapctruct的拷贝示例、以及四种方法时间对比。
    

    Mapstuct介绍

    1.mapstruct的官网地址:
    https://mapstruct.org

    2.mapstruct的文档地址:
    https://mapstruct.org/documentation/stable/reference/html/

    3.mapstrcut的示例github地址
    https://github.com/mapstruct/mapstruct-examples

    4.mapstruct的介绍
    mapstruct的作用:就像mapstruct官网所说的:mapsrtuct是一个用于简化在JavaBean之间映射的代码生成器工具,并且是基于约定高于配置的方式。

        因为生成的代码使用简单的get/set方法,所以mapstruct可以更快执行、类型之间复制更安全、且容易理解。
    

    mapstruct的优缺点

    下面看看mapstruct相比其他映射工具有什么优点

    1.mapstruct的优点:
    mapstruct是在代码编译的时候,生成其映射规则的代码,所以会在编译时暴露映射错误的代码,让错误提前暴露。

    因为使用的是一些简单方法:set/get或者Fluent方式,而非反射方式,所以可以更快的执行完成。可以通过04章节查看各个方法效率上对比

    可以实现深拷贝,上面4种方法中只有mapstruct可以实现深拷贝。但是需要进行配置(使用@mapper(mappingControl=DeepClone.class)进行设置)。其他的都是浅拷贝。从而mapstruct实现修改新对象不会对老对象产生影响。

    类型更加安全

    可以进行自定义的映射。可以自定义各种方法,完成属性映射。例如:将两个属性数据合并成一个设置到目标属性上

    2.mapstruct的缺点
    必须添加一个接口或者抽象类,才能实现映射。其他的三种方法都不用写额外接口或者类。

    Mapstruct的简单示例使用

    上面主要是介绍一下Mapstruct的基础知识,下面看一个mapstruct的简单示例,完成属性之间的映射。

        在示例中,我们使用mapstruct的1.4.2.Final版本,进行试验的
    
        1.第一个原属性数据
    
    //第一个拷贝对象
    public class CompareA {
     
        private String name;
     
        private Integer age;
     
        private LocalDateTime createTime;
     
        private double score;
     
        private Double totalScore;
     
        private Date updateTIme;
     
        private ChildCompare childCompare;
     
        private Long days;
        
        //省略其get/set方法,也可使用Lombok,以后讲解lombok与mapstruct结合使用
     }
    
    1. 第二个目标属性数据
    public class CompareB {
     
        private String name;
     
        private Integer age;
     
        private String createTime;
     
        private double score;
     
        private Double totalScore;
     
        private Date updateTIme;
     
        private ChildCompare childCompare;
     
        private Long day;
        
        //省略其get/set方法,
    }
    

    3.子类

    //这是CompareA和CompareB共有的对象
    public class ChildCompare {
     
        private String childName;
     
        private long childAge;
        
        //省略其get/set方法,
    }
    

    上面是两个实体对象,观察这两个实体可以看到有两点不同:

    CompareA中有一个createTime属性,数据类型为LocalDateTime,CompareB也有一个createTime,但是属性类型为String
    CompareA有一个days属性,而CompareB有一个day属性

    4.mapstruct接口(这是需要我们手动写的)

    
     
    
    @Mapper
    public interface CompareMapper {
     
        CompareMapper INSTANCE = Mappers.getMapper(CompareMapper.class);
     
        @Mapping(target = "day", source = "days")
        @Mapping(target = "createTime", source = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
        @Mapping(target = "childCompare", source = "childCompare", mappingControl = DeepClone.class)
        CompareB mapper(CompareA compareA);
    }
    

    从上面的实现中,我们加入了三个注解:

    第一个注解:完成属性名不匹配的问题,将compareA中的days(source)赋值到compareB的day(target)
    第二个注解:完成属性类型不匹配的问题,将compareA中的createTime,赋值到compareB的createTime,这里进行日期的格式转化,使用dateFormat设置格式化类型
    第三个注解:完成深度拷贝,将compareA中的childCompare属性进行深度拷贝,而不是指针复制,最重要的是最后一个参数:mappingControl = DeepClone.class

    5.最后就会自动生成一个实现类:

    
     
    
    @Generated(
        value = "org.mapstruct.ap.MappingProcessor"
    )
    public class CompareMapperImpl implements CompareMapper {
     
        @Override
        public CompareB mapper(CompareA compareA) {
            if ( compareA == null ) {
                return null;
            }
     
            CompareB compareB = new CompareB();
     
            compareB.setDay( compareA.getDays() );
            if ( compareA.getCreateTime() != null ) {
                compareB.setCreateTime( DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss" ).format( compareA.getCreateTime() ) );
            }
            compareB.setChildCompare( childCompareToChildCompare( compareA.getChildCompare() ) );
            compareB.setName( compareA.getName() );
            compareB.setAge( compareA.getAge() );
            compareB.setScore( compareA.getScore() );
            compareB.setTotalScore( compareA.getTotalScore() );
            compareB.setUpdateTIme( compareA.getUpdateTIme() );
     
            return compareB;
        }
     
        protected ChildCompare childCompareToChildCompare(ChildCompare childCompare) {
            if ( childCompare == null ) {
                return null;
            }
     
            ChildCompare childCompare1 = new ChildCompare();
     
            childCompare1.setChildName( childCompare.getChildName() );
            childCompare1.setChildAge( childCompare.getChildAge() );
     
            return childCompare1;
        }
    }
    

    从上面的实现,我们可以看出,添加一个childCompareToChildCompare方法,来完成对象之间的深度拷贝。同样的将days设置到了day属性,等等。

          6.最后,我们调用这个mapper方法,就可以完成对象之间的拷贝:如下:
    

    CompareMapper.INSTANCE.mapper(new CompareA());

    对象映射之间的比较

    
    
    public class CompareTest {
     
        int count = 1000000;
     
        /**
         * Spring中的BeanUtils的使用,最后使用了6700ms
         */
        @Test
        public void springBeanUtils() {
            CompareA populate = populate();
            StopWatch stopWatch = new StopWatch();
            stopWatch.start("开始拷贝");
            for (int i = 0; i < count; i++) {
                CompareB compareB = new CompareB();
                BeanUtils.copyProperties(populate, compareB);
            }
            stopWatch.stop();
            System.out.println(stopWatch.getTotalTimeMillis());
        }
     
        /**
         * 这是使用mapstruct进行对象拷贝,使用时间54ms
         */
        @Test
        public void mapstructBeanUtils() {
            CompareA populate = populate();
            StopWatch stopWatch = new StopWatch();
            stopWatch.start("开始拷贝");
            for (int i = 0; i < count; i++) {
                CompareB mapper = CompareMapper.INSTANCE.mapper(populate);
            }
            stopWatch.stop();
            System.out.println(stopWatch.getTotalTimeMillis());
        }
     
        /**
         * 这是Apache的BeanUtils工具,使用7086ms
         * @throws InvocationTargetException
         * @throws IllegalAccessException
         */
        @Test
        public void commonBeanUtils() throws InvocationTargetException, IllegalAccessException {
            CompareA populate = populate();
            StopWatch stopWatch = new StopWatch();
            stopWatch.start("开始拷贝");
            for (int i = 0; i < count; i++) {
                CompareB compareB = new CompareB();
                org.apache.commons.beanutils.BeanUtils.copyProperties(compareB, populate);
            }
            stopWatch.stop();
            System.out.println(stopWatch.getTotalTimeMillis());
        }
     
        /**
         * 使用Apache中的propertyUtils静态方法,使用3756ms
         * @throws IllegalAccessException
         * @throws NoSuchMethodException
         * @throws InvocationTargetException
         */
        @Test
        public void commonPropertiesUtils() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
            CompareA populate = populate();
            StopWatch stopWatch = new StopWatch();
            stopWatch.start("开始拷贝");
            for (int i = 0; i < count; i++) {
                CompareB compareB = new CompareB();
                PropertyUtils.copyProperties(compareB, populate);
            }
            stopWatch.stop();
            System.out.println(stopWatch.getTotalTimeMillis());
        }
     
        public CompareA populate() {
            CompareA compareA = new CompareA();
            compareA.setAge(10);
            compareA.setName("moxiao");
            compareA.setCreateTime(LocalDateTime.now());
            compareA.setDays(100L);
            compareA.setTotalScore(100.0);
            compareA.setScore(12.3);
            compareA.setUpdateTIme(new Date());
            ChildCompare childCompare = new ChildCompare();
            childCompare.setChildAge(200);
            childCompare.setChildName("moxiaoChild");
            compareA.setChildCompare(childCompare);
            return compareA;
        }
     
    }
    

    综上所述,1百万数据,mapstruct可以在50ms左右完成。

    Mapstruct的属性之间的映射规则

    在属性映射方面,mapstruct相比于其他映射工具有:

    • 可以进行不同属性名之间的映射,使用@Mapping注解的source和target
    • 可以使用表达式进行设置,使用@Mapping注解中的expression
    • 可以设置默认值,使用@Mapping注解中的constant,
    • 可以进行不同类型之间的映射,并且更加安全
    • 可以进行自定义映射方法

    mapstruct的映射控制说明

    2.1 映射控制的作用:

        在源对象和目标对象之间进行映射时,哪种映射方法将被考虑。即:只有在有这个控制条件下,才会执行对应的映射方法。
    
        所有属性之间的复制或者拷贝都将是依据以下映射控制来完成的。只有更好地理解这四种映射控制,才能按照我们的想法进行对象之间的拷贝。
    

    2.2 映射控制的种类:

    mapstruct一共有四种映射控制:

    MappingControl.Use.DIRECT
    直接映射:直接将源属性赋值到目标属性上,如果是对象的话,就是指针复制,也就是浅拷贝。这种方法有一个前提:目标属性是源属性的父类或者相同类型。

    MappingControl.Use.BUILT_IN_CONVERSION
    内置映射:将使用mapstruct内置的映射方法。有哪些内置映射方法,例如:日期和字符串、原生类型和对应的包装对象、字符串和枚举类型等等。

    MappingControl.Use.MAPPING_METHOD
    映射方法:包含两类:可以是自定义的映射方法,也可以是系统自动生成的映射方法。注意:自定义映射方法比系统自动生成的映射方法的优先级更高。例如:深度拷贝就是使用这个映射控制。系统自动生成的映射方法:一般都是对象之间的映射。

    MappingControl.Use.COMPLEX_MAPPING
    复合映射:是一种结合BUILT_IN_CONVERSION和MAPPING_METHOD的映射控制,来完成对象属性之间的拷贝。当进行COMPLEX_MAPPING时:一共有三种形态:

                a) target = method1( method2( source ) )
    
                b) target = method( conversion( source ) )
    
                c) target = conversion( method( source ) )
    
        其中method开头表示:自定义映射方法,conversion开头的表示:内置映射方法。
    
        注意:复合映射中只能进行两次转化,不能多于两次,也不能少于两次。这三种形态不含两个内置映射方法来完成属性之间的拷贝。即:至少有一个自定义的映射方法的存在。
    
        注意:在没有某一中映射控制时,就不会采用这种方式完成属性映射,例如:没有MAPPING_METHOD就会不采用自定义的映射方法完成属性映射。
    

    2.3 映射控组组合

        四种映射控制可以组合使用,即同时使用两个及以上的映射控制,从而在这些映射控制中选择一种方式使用。那这就涉及到映射控制之间优先级。
    

    2.4 mapstruct内置的映射控制组合

        在mapstruct中一共有三种内置的映射控制组合,以及自定义的映射组合。
    

    @MappingControl注解类

        该注解使用了全部的映射控制:DIRECT、MAPPING_METHOD、 BUILT_IN_CONVERSION、COMPLEX_MAPPING。这也这是:默认使用映射控制。
    

    @DeepClone注解类

       该注解只使用了:MAPPING_METHOD映射,当我们使用这个注解时,将不会采用其他的三种方式来完成属性之间的拷贝。
    

    @NoComplexMapping注解类

       改注解使用了三种:DIRECT、MAPPING_METHOD、 BUILT_IN_CONVERSION,即将不会使用复合映射方法完成属性之间的拷贝
    

    自定义的映射组合
    我们可以声明一个注解类,自定义只是用哪些映射控制,例如:只使用内置的映射方法

    @Retention(value = RetentionPolicy.CLASS)
    @MappingControl( MappingControl.Use.BUILT_IN_CONVERSION )
    public @interface BuildInConversionControl {
    }

    2.5 映射控制的使用

        mapstruct默认使用的是:@MappingControl注解类,即四种映射控制
    
        我们可以在@Mapper注解中的mappingControl属性中设置,他的属性值是一个注解类。在@Mapper注解中设置这个属性:将会应用到这个类中的所有方法的属性之间的拷贝
    
        我们也可以在@Mapping注解中的mappingControl属性中设置。在@Mapping注解中设置这个属性:将只会应用到指定属性上。
    
        @Mapping的优先级比@Mapper的高,即优先采用@Mapping,如果没有才会使用@Mapper进行属性之间的映射。
    

    mapstruct的映射控制优先级

    在有多个映射控制使用时,例如在使用:@MappingControl注解,mapstruct将会如何进行属性之间的映射。这里就涉及到四种映射控制之间的优先级。

    3.1 四种映射控制的优先级,从高到低

    在有MAPPING_METHOD控制下,并且包含有一个自定义的映射方法。这个自定义方法必须满足:输入参数为源属性父级或者相同类型,这个映射方法的返回值为目标属性的子类或相同类型。必须都满足这两个条件:这样在进行属性拷贝时,才会使用自定义的映射方法。不然则跳过。
    在有DIRECT控制下,并且目标属性必须是源属性的父类或者相同类型。功能:直接将源属性的指针拷贝到目标属性下。必须满足这两个条件,才会使用指针拷贝,不然则跳过。
    如果有BUILT_IN_CONVERSION的控制下,在源属性和目标属性之间拷贝时,mapstruct就会根据源属性类型和目标属性类型找到对应的内置映射方法使用,没有找到,就跳过。
    如果有COMPLEX_MAPPING控制下,它又划分成三种类型:
    如果存在两个自定义的方法,可以将源属性转化为目标属性,即: target = method1( method2( source ) ),优先使用。

                如果有一个自定义方法,一个内置映射方法,可以将源属性转化为目标属性,就会使用其中一个target = method( conversion( source ) )或者target = conversion( method( source ) )。
    
     5. 如果有MAPPING_METHOD控制下,将自动生成一个映射方法,完成属性之间的映射。必须对象,属性不能是:8中基本类型和对应的包装类以及String
    

    3.2 注意事项:

        如果源属性是8种基本类型或者包装体,而目标属性是对应的类型(不能是不对应的),则会直接拷贝。就算有就不会走上面的优先级。例如:源属性为long,目标属性为Long,不管配置的什么,都会直接赋值。
    

    mapstruct的映射控制的示例

    public class MappingOrder {
     
        private String name;
     
        private Integer age;
     
        private LocalDateTime birthTime;
     
        private MapperOrderChild mapperOrderChild;
     
        private MappingOrderChildChild mapperOrderChild2;
        //省略其set/get方法
     }
    

    目标对象

    public class MappingOrderVO {
     
        private String name;
     
        private Number age;
     
        private String birthString;
     
        private MapperOrderChild mapperOrderChild;
     
        private MapperOrderChild2 mapperOrderChild2;
     }
    

    映射类(必须自己单独定义一个,mapstruct必须提供一个mapper接口或者抽象类)

    
    @Mapper
    public interface MapperOrderMapper {
     
        @Mapping(source = "birthTime", target = "birthString", dateFormat = "yyyy-MM-dd HH:mm:ss")
        //这一行进行深度拷贝,注意最后一个参数很重要:mappingControl = DeepClone.class
        @Mapping(source = "mapperOrderChild2", target = "mapperOrderChild2", mappingControl = DeepClone.class)
        MappingOrderVO entityToVo(MappingOrder mappingOrder);
        
    }
    

    mapstruct自动生成的文件

    public class MapperOrderMapperImpl implements MapperOrderMapper {
     
        @Override
        public MappingOrderVO entityToVo(MappingOrder mappingOrder) {
            if ( mappingOrder == null ) {
                return null;
            }
     
            MappingOrderVO mappingOrderVO = new MappingOrderVO();
            
            //第一个属性,因为没有自定义方法从LocalDateTime转化为String,将跳过,
            //不能直接映射,优先级第二条
            //mapstruct有一个从LocalDateTime转化为String的内置方法,从而满足第三条映射
            if ( mappingOrder.getBirthTime() != null ) {
                mappingOrderVO.setBirthString( DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss" ).format( mappingOrder.getBirthTime() ) );
            }
            
            //我们在方法中使用DEEPCLONE,即MAPPING_METHOD控制
            //所以只有第一条优先级和第五条优先级,满足。因为没有自定义映射方法,从而跳过
            //所以Mapstruct使用第五条,自动生成一个映射方法
            mappingOrderVO.setMapperOrderChild2( mappingOrderChildChildToMapperOrderChild2( mappingOrder.getMapperOrderChild2() ) );
            //DIRECT优先级获胜
            mappingOrderVO.setName( mappingOrder.getName() );
            //DIRECT优先级获胜
            mappingOrderVO.setAge( mappingOrder.getAge() );
            //DIRECT优先级获胜
            mappingOrderVO.setMapperOrderChild( mappingOrder.getMapperOrderChild() );
            return mappingOrderVO;
        }
     
        protected MapperOrderChild2 mappingOrderChildChildToMapperOrderChild2(MappingOrderChildChild mappingOrderChildChild) {
            if ( mappingOrderChildChild == null ) {
                return null;
            }
            MapperOrderChild2 mapperOrderChild2 = new MapperOrderChild2();
     
            mapperOrderChild2.setFirstName( mappingOrderChildChild.getFirstName() );
            mapperOrderChild2.setSecondName( mappingOrderChildChild.getSecondName() );
     
            return mapperOrderChild2;
        }
    }
    
    更多相关内容
  • Spark SQL中StructField和StructType

    千次阅读 2022-02-28 15:28:41
    Spark SQL中的StructType以及StructField

    每一天都会进行更新,一起冲击未来

    StructField和StructType

            StructType---定义数据框的结构

            StructType定义DataFrame的结构,是StructField对象的集合或者列表,通过printSchema可以打印出所谓的表字段名,StructType就是所有字段的集合。在创建dataframe的时候,将StructType作为字段的集合,按照顺序一一给各个字段。

            StructField--定义DataFrame列的元数据

            StructField来定义列名,列类型,可为空的列和元数据。

    将StructField和StructType和DataFrame一起使用

            首先创建样例类

    case class StructType(fields: Array[StructField])
     case class StructField(
     name: String, 
    dataType: DataType, 
    nullable: Boolean = true, 
    metadata: Metadata = Metadata.empty)

            创建相关的数据以及字段名

    //创建数据集合
    val simpleData = Seq(
    Row("James ","","Smith","36636","M",3000), 
    Row("Michael ","Rose","","40288","M",4000), 
    Row("Robert ","","Williams","42114","M",4000), 
    Row("Maria ","Anne","Jones","39192","F",4000), 
    Row("Jen","Mary","Brown","","F",-1) ) 
    //创建StructType对象,里面是Array[StructField]类型
    val simpleSchema = StructType(Array(
     StructField("firstname",StringType,true), 
    StructField("middlename",StringType,true), 
    StructField("lastname",StringType,true), 
    StructField("id", StringType, true), 
    StructField("gender", StringType, true), 
    StructField("salary", IntegerType, true) )) 
    //创建dataFrame
    val df = spark.createDataFrame( 
    spark.sparkContext.parallelize(simpleData),simpleSchema)
    //打印Schema
     df.printSchema() 
    

            代码很简答,需要一个数据集合,创建一个StructType对象,里面包含StructField对象。

            前面说过,StructField对象里面包含的是列名以及各种信息。

            创建DataFrame。此时,元数据就是simpleData,所谓的Schema就是simpleSchema。

            看一下各个字段以及“表结构”

     

            其实上面的案例也比较有一些麻烦,下面来看一下另外一种方法,不用创建样例类

    通过StructType.add进行操作

            通过StructType.add进行操作,意味着我们不用再去创建StructField对象,通过add方法,只需要写入字段名称和字段方法就可以完成这个操作。

    //创建上下文环境 SparkSql环境
    val sparkSQL = new SparkConf().setMaster("local[*]").setAppName("SparkSQL") 
    val sparkSession = SparkSession.builder().config(sparkSQL).getOrCreate() 
    import sparkSession.implicits._ 
    //数据集合 
    val simpData = Seq(Row("James", "", "Smith", "36636", "M", 3000), 
    Row("Michael", "Rose", "", "40288", "M", 4000),
     Row("Robert", "", "Williams", "42114", "M", 4000), 
    Row("Maria", "Anne", "Jones", "39121", "F", 4000), 
    Row("Jen", "Mary", "Brown", "", "F", -1))
     //创建StructType对象,将字段进行累加 
    val structType = new StructType()
    .add("firstname", StringType) 
    .add("middlename", StringType) 
    .add("lastname", StringType) 
    .add("id", StringType) 
    .add("gender", StringType) 
    .add("salary", StringType)
     //创建DataFrame
     val dataFrame = sparkSession.createDataFrame(
    sparkSession.sparkContext.parallelize(simpData), structType) 
    dataFrame.printSchema() 
    sparkSession.close()

            同样也是需要数据集合以及StructType对象。不过这种操作更加的简便,重要的是不会报错,用最上面的方法创建样例类可能会报错,需要导入不同的包。

    使用StructType进行嵌套字段

    //创建Spark SQL环境
    val sparkSQL = new SparkConf().setMaster("local[*]").setAppName("SparkSQL") 
    val sparkSession = SparkSession.builder().config(sparkSQL).getOrCreate() 
    import sparkSession.implicits._ 
    //创建数据集,其中最里面的Row对象就是嵌套对象
    val structData = Seq( Row(Row("James ", "", "Smith"), "36636", "M", 3100),
     Row(Row("Michael ", "Rose", ""), "40288", "M", 4300), 
    Row(Row("Robert ", "", "Williams"), "42114", "M", 1400), 
    Row(Row("Maria ", "Anne", "Jones"), "39192", "F", 5500),
     Row(Row("Jen", "Mary", "Brown"), "", "F", -1)) 
    //通过StructType的add方法进行添加字段
    val structType = new StructType()
    .add("name",new StructType() 
    .add("firstname",StringType) 
    .add("middlename",StringType) 
    .add("lastname",StringType)) 
    .add("id",StringType) 
    .add("gender",StringType) 
    .add("salary",StringType)
    //创建dataframe 
    val dataFrame = 
    sparkSession.createDataFrame(
    sparkSession.sparkContext.parallelize(structData), structType) 
    //打印schema
    dataFrame.printSchema() 
    sparkSession.close()

            因为name字段进行了嵌套,因此在"name"字段后面的类型里面不再是StringType.而是一个嵌套类型 StructType,这个嵌套类型里面再继续进行add。在这里面嵌套了三个字段。

            可以看上面Schema。那么字段的类型是Struct结构。这个Struct结构里面嵌套了三个字段。

            其实上面写错了,纠正一下,最后一个字段应该是IntegerType类型

            如果写StringType类型,虽然打印Schema没有报错,但是进行select的时候就会报错。所以需要进行修改,在这里说明一下。

            dataFrame.select("name").show(false)

            看一下嵌套字段的name

     

             本来以为Spark SQL的知识只有一点点,没有想到的是Spark SQL里面的知识很多很多,不单单是SQL语言,虽然可以结合Hive或者Mysql写SQL,但是结构化数据使用本身的DSL+SQL更加的简单。

            SQL是重中之重,SQL能解决90%问题,剩下解决不了的问题就交给RDD把        

    
                                            
    展开全文
  • Mapstruct使用说明(一)

    千次阅读 2021-09-08 09:31:35
    在使用分层或者分模块化的项目中,我们可能定义各种各样的O,例如:DO,VO,DTO等等。我们在进行这些对象之间的拷贝时,通过手动写get/set方法进行属性之间的赋值。... mapstruct提供Mappers ...

            在使用分层或者分模块化的项目中,我们可能定义各种各样的O,例如:DO,VO,DTO等等。我们在进行这些对象之间的拷贝时,通过手动写get/set方法进行属性之间的赋值。因为他们之间的属性大部分都是相同的,不仅浪费时间,并且还有大量重复代码。所以,各种框架都添加的对象之间的拷贝的工具类。例如:

    1. Spring自带了BeanUtils

    2. Apatch自带的BeanUtils

    3. Apatch自带的PropertyUtils

    4. mapstruct提供Mappers

            本文主要介绍MapStruct的基础知识、Mapstruct的优缺点、Mapctruct的拷贝示例、以及四种方法时间对比。

    01

    Mapstuct介绍


    1.mapstruct的官网地址:   

            https://mapstruct.org

    2.mapstruct的文档地址:

            https://mapstruct.org/documentation/stable/reference/html/

    3.mapstrcut的示例github地址

            https://github.com/mapstruct/mapstruct-examples

    4.mapstruct的介绍

            mapstruct的作用:就像mapstruct官网所说的:mapsrtuct是一个用于简化在JavaBean之间映射的代码生成器工具,并且是基于约定高于配置的方式。

            因为生成的代码使用简单的get/set方法,所以mapstruct可以更快执行、类型之间复制更安全、且容易理解。

    02

    mapstruct的优缺点


    下面看看mapstruct相比其他映射工具有什么优点

    1.mapstruct的优点:

    • mapstruct是在代码编译的时候,生成其映射规则的代码,所以会在编译时暴露映射错误的代码,让错误提前暴露。

    • 因为使用的是一些简单方法:set/get或者Fluent方式,而非反射方式,所以可以更快的执行完成。可以通过04章节查看各个方法效率上对比

    • 可以实现深拷贝,上面4种方法中只有mapstruct可以实现深拷贝。但是需要进行配置(使用@mapper(mappingControl=DeepClone.class)进行设置)。其他的都是浅拷贝。从而mapstruct实现修改新对象不会对老对象产生影响。

    • 类型更加安全

    • 可以进行自定义的映射。可以自定义各种方法,完成属性映射。例如:将两个属性数据合并成一个设置到目标属性上

    2.mapstruct的缺点

    • 必须添加一个接口或者抽象类,才能实现映射。其他的三种方法都不用写额外接口或者类。

    03

    Mapstruct的简单示例使用


            上面主要是介绍一下Mapstruct的基础知识,下面看一个mapstruct的简单示例,完成属性之间的映射。

            在示例中,我们使用mapstruct的1.4.2.Final版本,进行试验的

            1.第一个原属性数据

    //第一个拷贝对象
    public class CompareA {
    
        private String name;
    
        private Integer age;
    
        private LocalDateTime createTime;
    
        private double score;
    
        private Double totalScore;
    
        private Date updateTIme;
    
        private ChildCompare childCompare;
    
        private Long days;
        
        //省略其get/set方法,也可使用Lombok,以后讲解lombok与mapstruct结合使用
     }

           2. 第二个目标属性数据

    public class CompareB {
    
        private String name;
    
        private Integer age;
    
        private String createTime;
    
        private double score;
    
        private Double totalScore;
    
        private Date updateTIme;
    
        private ChildCompare childCompare;
    
        private Long day;
        
        //省略其get/set方法,
    }

           3.子类

    //这是CompareA和CompareB共有的对象
    public class ChildCompare {
    
        private String childName;
    
        private long childAge;
        
        //省略其get/set方法,
    }

            上面是两个实体对象,观察这两个实体可以看到有两点不同:

    • CompareA中有一个createTime属性,数据类型为LocalDateTime,CompareB也有一个createTime,但是属性类型为String
    • CompareA有一个days属性,而CompareB有一个day属性

            4.mapstruct接口(这是需要我们手动写的)

    package com.moxiao.properties.mapstruct;
    
    import com.moxiao.properties.entity.CompareA;
    import com.moxiao.properties.entity.CompareB;
    import org.mapstruct.Mapper;
    import org.mapstruct.Mapping;
    import org.mapstruct.control.DeepClone;
    import org.mapstruct.factory.Mappers;
    
    /**
     * @author moxiao
     */
    @Mapper
    public interface CompareMapper {
    
        CompareMapper INSTANCE = Mappers.getMapper(CompareMapper.class);
    
        @Mapping(target = "day", source = "days")
        @Mapping(target = "createTime", source = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
        @Mapping(target = "childCompare", source = "childCompare", mappingControl = DeepClone.class)
        CompareB mapper(CompareA compareA);
    }

            从上面的实现中,我们加入了三个注解:

    • 第一个注解:完成属性名不匹配的问题,将compareA中的days(source)赋值到compareB的day(target)
    • 第二个注解:完成属性类型不匹配的问题,将compareA中的createTime,赋值到compareB的createTime,这里进行日期的格式转化,使用dateFormat设置格式化类型
    • 第三个注解:完成深度拷贝,将compareA中的childCompare属性进行深度拷贝,而不是指针复制,最重要的是最后一个参数:mappingControl = DeepClone.class

            5.最后就会自动生成一个实现类:

    package com.moxiao.properties.mapstruct;
    
    import com.moxiao.properties.entity.ChildCompare;
    import com.moxiao.properties.entity.CompareA;
    import com.moxiao.properties.entity.CompareB;
    import java.time.format.DateTimeFormatter;
    import javax.annotation.Generated;
    
    @Generated(
        value = "org.mapstruct.ap.MappingProcessor"
    )
    public class CompareMapperImpl implements CompareMapper {
    
        @Override
        public CompareB mapper(CompareA compareA) {
            if ( compareA == null ) {
                return null;
            }
    
            CompareB compareB = new CompareB();
    
            compareB.setDay( compareA.getDays() );
            if ( compareA.getCreateTime() != null ) {
                compareB.setCreateTime( DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss" ).format( compareA.getCreateTime() ) );
            }
            compareB.setChildCompare( childCompareToChildCompare( compareA.getChildCompare() ) );
            compareB.setName( compareA.getName() );
            compareB.setAge( compareA.getAge() );
            compareB.setScore( compareA.getScore() );
            compareB.setTotalScore( compareA.getTotalScore() );
            compareB.setUpdateTIme( compareA.getUpdateTIme() );
    
            return compareB;
        }
    
        protected ChildCompare childCompareToChildCompare(ChildCompare childCompare) {
            if ( childCompare == null ) {
                return null;
            }
    
            ChildCompare childCompare1 = new ChildCompare();
    
            childCompare1.setChildName( childCompare.getChildName() );
            childCompare1.setChildAge( childCompare.getChildAge() );
    
            return childCompare1;
        }
    }
    

              从上面的实现,我们可以看出,添加一个childCompareToChildCompare方法,来完成对象之间的深度拷贝。同样的将days设置到了day属性,等等。

              6.最后,我们调用这个mapper方法,就可以完成对象之间的拷贝:如下:

    CompareMapper.INSTANCE.mapper(new CompareA());

    04

    这个对象映射之间的比较


            我们在1,000,000个对象进行各个工具之间的对比,看看效率如何?

    package com.moxiao.properties.mapstruct;
    
    import com.moxiao.properties.entity.ChildCompare;
    import com.moxiao.properties.entity.CompareA;
    import com.moxiao.properties.entity.CompareB;
    import org.apache.commons.beanutils.PropertyUtils;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.BeanUtils;
    import org.springframework.util.StopWatch;
    
    import java.lang.reflect.InvocationTargetException;
    import java.time.LocalDateTime;
    import java.util.Date;
    
    /**
     * @author moxiao
     */
    public class CompareTest {
    
        int count = 1000000;
    
        /**
         * Spring中的BeanUtils的使用,最后使用了6700ms
         */
        @Test
        public void springBeanUtils() {
            CompareA populate = populate();
            StopWatch stopWatch = new StopWatch();
            stopWatch.start("开始拷贝");
            for (int i = 0; i < count; i++) {
                CompareB compareB = new CompareB();
                BeanUtils.copyProperties(populate, compareB);
            }
            stopWatch.stop();
            System.out.println(stopWatch.getTotalTimeMillis());
        }
    
        /**
         * 这是使用mapstruct进行对象拷贝,使用时间54ms
         */
        @Test
        public void mapstructBeanUtils() {
            CompareA populate = populate();
            StopWatch stopWatch = new StopWatch();
            stopWatch.start("开始拷贝");
            for (int i = 0; i < count; i++) {
                CompareB mapper = CompareMapper.INSTANCE.mapper(populate);
            }
            stopWatch.stop();
            System.out.println(stopWatch.getTotalTimeMillis());
        }
    
        /**
         * 这是Apache的BeanUtils工具,使用7086ms
         * @throws InvocationTargetException
         * @throws IllegalAccessException
         */
        @Test
        public void commonBeanUtils() throws InvocationTargetException, IllegalAccessException {
            CompareA populate = populate();
            StopWatch stopWatch = new StopWatch();
            stopWatch.start("开始拷贝");
            for (int i = 0; i < count; i++) {
                CompareB compareB = new CompareB();
                org.apache.commons.beanutils.BeanUtils.copyProperties(compareB, populate);
            }
            stopWatch.stop();
            System.out.println(stopWatch.getTotalTimeMillis());
        }
    
        /**
         * 使用Apache中的propertyUtils静态方法,使用3756ms
         * @throws IllegalAccessException
         * @throws NoSuchMethodException
         * @throws InvocationTargetException
         */
        @Test
        public void commonPropertiesUtils() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
            CompareA populate = populate();
            StopWatch stopWatch = new StopWatch();
            stopWatch.start("开始拷贝");
            for (int i = 0; i < count; i++) {
                CompareB compareB = new CompareB();
                PropertyUtils.copyProperties(compareB, populate);
            }
            stopWatch.stop();
            System.out.println(stopWatch.getTotalTimeMillis());
        }
    
        public CompareA populate() {
            CompareA compareA = new CompareA();
            compareA.setAge(10);
            compareA.setName("moxiao");
            compareA.setCreateTime(LocalDateTime.now());
            compareA.setDays(100L);
            compareA.setTotalScore(100.0);
            compareA.setScore(12.3);
            compareA.setUpdateTIme(new Date());
            ChildCompare childCompare = new ChildCompare();
            childCompare.setChildAge(200);
            childCompare.setChildName("moxiaoChild");
            compareA.setChildCompare(childCompare);
            return compareA;
        }
    
    }

            pom文件如下:

    
    <?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.moxiao</groupId>
        <artifactId>propertiescopytest</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.3.9</version>
            </dependency>
            
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>5.3.9</version>
            </dependency>
            
            <dependency>
                <groupId>org.mapstruct</groupId>
                <artifactId>mapstruct</artifactId>
                <version>1.4.2.Final</version>
            </dependency>
    
            <!-- lombok dependencies should not end up on classpath -->
            <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.18</version>
                <scope>provided</scope>
            </dependency>
    
            <dependency>
                <groupId>commons-beanutils</groupId>
                <artifactId>commons-beanutils</artifactId>
                <version>1.9.4</version>
            </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-mapstruct-binding</artifactId>
                                <version>0.2.0</version>
                            </path>
                            <path>
                                <groupId>org.mapstruct</groupId>
                                <artifactId>mapstruct-processor</artifactId>
                                <version>1.4.2.Final</version>
                            </path>
                            <path>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                                <version>1.18.18</version>
                            </path>
                        </annotationProcessorPaths>
                        <showWarnings>true</showWarnings>
                        <compilerArgs>
                            <arg>
                                -Amapstruct.suppressGeneratorTimestamp=true
                            </arg>
                            <arg>
                                -Amapstruct.suppressGeneratorVersionInfoComment=true
                            </arg>
                        </compilerArgs>
    
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
    </project>

    上面是各个工具之间的对比,1000000数据之间拷贝的时间为:

    工具名称时间(ms)
    mapstruct54
    Spring的BeanUtils6700
    Apache的common的BeanUtils7086
    Apache的common的PropertyUtils3756

    综上所述,1百万数据,mapstruct可以在50ms左右完成。

    这篇文章只是Mapstruct文章的开头,后续还有:

    • 与Lombok结合使用以及注意事项。
    • 与SpringBoot进行DI
    • 对象之间的深度拷贝,需要最什么配置

    更多精彩内容:请关注公众号:


     

    展开全文
  • C++之struct

    千次阅读 2022-04-05 19:22:00
    C++之struct

    一、概念

    结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构。它就将不同类型的数据存放在一起,作为一个整体进行处理。

    结构体在函数中的作用不是简便,其最主要的作用就是封装。封装的好处就是可以再次利用。让使用者不必关心这个是什么,只要根据定义使用就可以了。

    结构体的大小不是结构体元素单纯相加就行的,因为我们现在主流的计算机使用的都是32Bit字长的CPU,对这类型的CPU取4个字节的数要比取一个字节要高效,也更方便。所以在结构体中每个成员的首地址都是4的整数倍的话,取数据元素时就会相对更高效,这就是内存对齐的由来。每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragmapack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的“对齐系数”。

    二、规则

    1、数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragmapack指定的数值和这个数据成员自身长度中,比较小的那个进行。

    2、结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragmapack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。

    3、结合1、2可推断:当#pragmapack的n值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果。

    三、结构体的定义和使用

    语法:struct 结构体名 { 结构体成员列表 };

    • struct 结构体名 变量名
    • struct 结构体名 变量名 = { 成员1值 , 成员2值…}
    • 定义结构体时创建变量
    #include <stdio.h>
    #include <iostream>
    #include <string>
    
    using namespace std;
     
    //结构体变量创建方式3:定义结构体时顺便创建变量
    struct student
    {
         //成员列表
         string name;
         int age;
         int score;   
    }stu3;
     
     
    int main(){
       
        //结构体变量创建方式1: struct 结构体名 变量名
        struct student stu1;
     
        stu1.name = "七喜";
        stu1.age = 20;
        stu1.score = 95;
        cout<<"姓名:"<<stu1.name <<" 年龄:"<<stu1.age <<" 分数:"<<stu1.score <<endl;
     
     
        //创建结构体变量方式2:struct 结构体名 变量名 = { 成员1值 , 成员2值…}
        struct student stu2 = {"可乐",19,100};
        cout<< "姓名:"<< stu2.name <<" 年龄:"<<stu2.age<<" 分数:"<<stu2.score<< endl;
     
     
        //结构体变量创建方式3:
        stu3.name = "雪碧";
        stu3.age  = 20;
        stu3.score = 90;
        cout<<"姓名:"<<stu3.name <<" 年龄:"<<stu3.age<<" 分数:"<<stu3.score<< endl;
     
        return 0;
    }
    

    四、结构体数组

    作用:将自定义的结构体放入到数组中方便维护

    语法: struct 结构体名 数组名[元素个数] = { { } , { } ,…, { } }

    #include <stdio.h>
    #include <iostream>
    #include <string>
    
    using namespace std;
     
    //结构体变量创建方式3:定义结构体时顺便创建变量
    struct student
    {
         //成员列表
         string name;
         int age;
         int score;   
    };
    
    int main(){
       //结构体数组
       struct student stus[3] = {{"康师傅",20,95},{"百事",19,100},{"农夫山泉",20,90}};
       for(int i=0; i < 3; i++){
          cout<<"姓名:"<<stus[i].name <<" 年龄:"<<stus[i].age<<" 分数:"<<stus[i].score<< endl;
       }
     
        return 0;
    }
    

    五、结构体指针

    . 和-> 区别:

    . 来访问结构体成员/属性

    -> 来访问其指向的结构体成员/属性

    #include <stdio.h>
    #include <iostream>
    #include <string>
    
    using namespace std;
     
    //结构体变量创建方式3:定义结构体时顺便创建变量
    struct student
    {
         //成员列表
         string name;
         int age;
         int score;   
    };
     
     
    int main(){
       
        //结构体变量创建方式1: struct 结构体名 变量名
        struct student stu1;
     
        stu1.name = "七喜";
        stu1.age = 20;
        stu1.score = 95;
        cout<<"姓名:"<<stu1.name <<" 年龄:"<<stu1.age <<" 分数:"<<stu1.score <<endl;
    
    
       //结构体指针
       struct student *p = &stu1;
       cout<<"姓名:"<<(*p).name <<" 年龄:"<<(*p).age<<" 分数:"<<(*p).score<< endl;
       cout<<"姓名:"<< p->name <<" 年龄:"<< p->age<<" 分数:"<< p->score<< endl;
    
     
        return 0;
    }
    

    六、结构体嵌套

    #include <stdio.h>
    #include <iostream>
    #include <string>
    
    using namespace std;
     
    //结构体变量创建方式3:定义结构体时顺便创建变量
    struct student
    {
         //成员列表
         string name;
         int age;
         int score;   
    };
    
    
    struct teacher
    {
        //成员列表
        int id; //职工编号
        string name;  //教师姓名
        int age;   //教师年龄
        struct student stu; //子结构体 学生
    };
    
     
     
    int main(){
    
       //结构体嵌套
       struct teacher t1;
        t1.id = 10000;
        t1.name = "老王";
        t1.age = 40;
     
        t1.stu.name = "张三";
        t1.stu.age = 18;
        t1.stu.score = 100;
     
        cout << " 教师 职工编号: " << t1.id << 
                " 姓名: " << t1.name << 
                " 年龄: " << t1.age << endl;
        
        cout << " 辅导学员 姓名: " << t1.stu.name << 
                " 年龄:" << t1.stu.age << 
                " 考试分数: " << t1.stu.score << endl;
    
    
     
        return 0;
    }
    

    七、结构体做函数参数

    传递方式包括:值传递、地址传递

    #include <stdio.h>
    #include <iostream>
    #include <string>
    
    using namespace std;
     
    //结构体变量创建方式3:定义结构体时顺便创建变量
    struct student
    {
         //成员列表
         string name;
         int age;
         int score;   
    };
    
    //值传递
    void printStudent1(student stu){
        stu.age = 28;
        cout << "子函数中 姓名:" << stu.name << 
        " 年龄: " << stu.age  << 
        " 分数:" << stu.score << endl;
    
    }
    
    
    //地址传递
    void printStudent2(student *stu)
    {
        stu->age = 28;
        cout << "子函数中 姓名:" << stu->name << 
                " 年龄: " << stu->age  << 
                " 分数:" << stu->score << endl;
    }
    
     
     
    int main(){
       
        //结构体做函数参数
        struct student stu1;
        stu1.name = "七喜";
        stu1.age = 20;
        stu1.score = 95;
        cout<<"姓名:"<<stu1.name <<" 年龄:"<<stu1.age <<" 分数:"<<stu1.score <<endl
    
        
        printStudent1(stu1);
        printStudent2(&stu1);
    
        return 0;
    }
    
    展开全文
  • mapstruct使用的正确姿势

    万次阅读 多人点赞 2020-04-22 09:29:29
    我们都知道,随着一个工程的越来越成熟,模块划分会越来越细,其中实体类一般存于 domain 之中,但 domain 工程最好不要被其他工程依赖,所以其他工程想...所以阿淼今天就要给大家安利一款叫 mapstruct 的插件,它就...
  • 一、vm_area_struct 结构体、 二、task_struct 进程描述符、mm_struct 内存描述符、vm_area_struct 虚拟内存区间 之间的关系
  • struct files_structstruct fdtable

    千次阅读 2018-05-30 18:11:09
    struct files_structstruct fdtable的初始化我们先来列出struct files_structstruct fdtable的定义,为了讨论方面,下面的定义中略去了很少一部分的锁成员,下面的代码均摘自linux 2.6.24。struct files_struct...
  • MapStruct - 一篇就能上手 MapStruct

    万次阅读 多人点赞 2021-02-22 17:45:25
    MapStruct是满足JSR269规范的一个Java注解处理器,用于为Java Bean生成类型安全且高性能的映射。它基于编译阶段生成get/set代码,此实现过程中没有反射,不会造成额外的性能损失。 您所要做的就是定义一个mapper...
  • mapstruct原理解析

    万次阅读 2021-09-09 20:06:31
    目录 一、mapstruct简介 二、mapstruct与其他映射框架...有了mapstruct,只需要定义一个映射器接口,声明需要映射的方法,在编译过程中,mapstruct会自动生成该接口的实现类,实现将源对象映射到目标对象的效果。 ...
  • 自定义结构体类型:struct使用详解

    千次阅读 多人点赞 2021-03-09 10:37:25
    文章目录系列文章目录一、结构体(struct)二、使用步骤1.引入库2.读入数据总结 一、结构体(struct) 在程序设计时,最重要的步骤之一就是选择表示数据的方法。在许多的情况下,简单变量甚至是数组还不足以表示一...
  • c语言struct用法详解

    千次阅读 2021-05-18 16:28:14
    c语言struct用法详解在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据。结构体的定义形式为:struct 结构体名{结构体所包含的变量或数组};结构体是一种集合,它里面包含了多个变量或数组,它们的类型可以...
  • struct 结构体,到底如何用啊

    千次阅读 2021-05-23 00:35:41
    当前位置:我的异常网» C语言»struct 结构体,到底如何用啊struct 结构体,到底如何用啊www.myexceptions.net网友分享于:2014-04-22浏览:3次struct 结构体,到底怎么用啊???#include#include#include#...
  • C语言中的struct用法

    万次阅读 多人点赞 2019-06-24 15:01:52
    参考自C语言中的struct用法 在c语言中结构体(struct)跟面向对象编程(如java等)里面的类是非常相似的。不过像C++里面对结构体进行了扩展,c++里面的结构体是可以包含方法的,但是C语言里面是不能够的。 结构...
  • JavaStruct

    千次阅读 2018-05-08 15:36:18
    javastruct A library to treat java objects as C structs. 一个将java对象视为C结构的库 窗体顶端 窗体底端 Project HomeDownloadsWikiIssuesSource Search 窗体顶端 for 窗体底端 HowToUseJavaStruct ...
  • python之struct 模块详解

    千次阅读 2021-01-18 19:52:26
    struct 模块 一、struct简单介绍 注意:本文中出现的四个名词同义:二进制流、二进制数组、字节流、字节数组 1.引入 准确地讲,Python没有专门处理字节的数据类型。但由于b'str'可以表示字节,所以,字节数组=二...
  • Go基础系列:struct和嵌套struct

    千次阅读 2018-10-31 13:10:12
    struct struct定义结构,结构由字段(field)组成,每个field都有所属数据类型,在一个struct中,每个字段名都必须唯一。 说白了就是拿来存储数据的,只不过可自定义化的程度很高,用法很灵活,Go中不少功能依赖于结构...
  • struct和typedef struct彻底明白了

    万次阅读 多人点赞 2019-09-07 19:43:36
    C/C++语法知识:typedef struct 用法详解 typedef struct OLNode {  int i,j;  int data;  OLNode *right,*down; }OLNode,*OLink;//结构的对象OLNode, 指向结构的指针*OLink, 可以这样写 struct OLNode{}; ...
  • 进程控制块Task_struct

    千次阅读 2021-11-23 23:45:00
    文章目录进程的定义进程的创建进程的退出Task_struct 结构Task_struct 这里不讲进程的基本原理,重点描述下进程的数据结构(task_struct). 进程的定义 正在执行的程序 正在计算机上执行的程序实例 能分配给处理器并...
  • struct sockaddr_in struct sockaddr struct in_addr 这三个结构体在网络编程中经常忘记各自的成员,需要临时查阅。 struct sockaddr { /***** 地址族 AF_xxx *****/ unsigned short sa_family; /***** 14字节的...
  • python之struct详解

    万次阅读 多人点赞 2018-05-23 18:20:29
    用处按照指定格式将Python数据转换为...处理二进制数据,如果用struct来处理文件的话,需要用’wb’,’rb’以二进制(字节流)写,读的方式来处理文件;处理c语言中的结构体;struct模块中的函数函数returnexplainpack(fmt,...
  • 结构体的一般定义形式为: struct 结构体名{ 类型名1 成员名1; 类型名2 成员名2; …… 类型名n 成员名n; }; 2、举例 比如,我们定义一个学生 struct Student{ char*name;//姓名 int age;//年龄 float height;//...
  • Python数据结构与算法(10)---二进制数据结构Struct

    万次阅读 多人点赞 2021-04-19 12:20:29
    目录前言 前言 在C/C++语言中,struct被称为结构体。而在Python中,struct是一个专门的库,用于处理字节串与原生Python数据结构类型之间的转换。
  • 【C/C++面试必备】struct和class的区别

    万次阅读 多人点赞 2021-07-23 07:47:53
    ???? 作者:Linux猿 ???? 简介:CSDN博客专家?...,C/C++、面试、刷题、算法尽管咨询我,关注我,有...首先,注意本文讨论的是 C++ 中 struct 和 class 的区别,因为 C 中 struct 和 class 的区别已经很明显了! 先说下
  • 如何解决mapstruct和lombok冲突问题

    千次阅读 2022-01-06 22:09:35
    在按照官网配置mapstruct,使用lombok。当我们在maven install时候会出现属性找不到错误。 二、解决配置如下 确保 Lombok 最低版本为 1.18.16 annotationProcessorPaths 中,要配置lombok <build> <...
  • static struct、typedef struct

    千次阅读 2020-12-09 10:51:16
    static struct { char a; char b; } hrpsCb; 测试程序如下 #include <stdio.h> static struct { char a; char b; } hrpsCb; int main() { hrpsCb.a = 1; hrpsCb.b = 2; printf("Hello, World! %d %d\n...
  • matlab基本数据结构struct

    千次阅读 2021-04-21 06:32:08
    一起来学演化计算-matlab基本数据结构struct觉得有用的话,欢迎一起讨论相互学习~Follow Me结构数组structMATLAB提供了两种定义结构的方式:直接应用和使用struct函数使用直接引用方式定义结构与建立数值型数组一样,...
  • 使用MapStruct映射集合

    千次阅读 2021-04-25 19:30:40
    通常,使用MapStruct映射集合的方式与使用简单类型的方式相同。 基本上,必须创建一个简单的接口或抽象类并声明映射方法。 根据声明,MapStruct将自动生成映射代码。 通常,生成的代码将遍历源集合,将每个元素转换...
  • MapStruct超级简单的学习笔记

    万次阅读 多人点赞 2019-02-14 11:23:26
    MapStruct使用MapStruct1.MapStruct是用来做什么的?2.使用MapStruct解决上述问题3.添加默认方法4. 可以使用abstract class来代替接口5.可以使用多个参数5.直接使用参数作为属性值 使用MapStruct 首先来了解一下DTO...
  • C语言之struct 和 typedef struct

    千次阅读 2020-10-07 17:21:34
    struct 用法 struct tag { member-list member-list member-list ... } variable-list ; 实例 struct Books { int book_id; char *bookname; } 说明: (1)上面声明了一个结构的“变量类型”,我们...
  • Hive Struct to String转换(Hive Struct to String conversion)我有一个包含结构的表 - 让我们说:create external table table1 (a int,b STRUCT ,e string)我在这张桌子上执行选择,得到类似的东西 -1100 {“c”:...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,621,320
精华内容 1,048,528
关键字:

struct

友情链接: Mifare1kTest.zip